bitkeeper revision 1.1159.1.505 (41cfdff23HZ-hiPuiX8jOHYDydBmgA)
authorcl349@arcadians.cl.cam.ac.uk <cl349@arcadians.cl.cam.ac.uk>
Mon, 27 Dec 2004 10:12:02 +0000 (10:12 +0000)
committercl349@arcadians.cl.cam.ac.uk <cl349@arcadians.cl.cam.ac.uk>
Mon, 27 Dec 2004 10:12:02 +0000 (10:12 +0000)
sync w/ head.

29 files changed:
1  2 
.rootkeys
linux-2.6.10-xen-sparse/arch/xen/Kconfig
linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig
linux-2.6.10-xen-sparse/arch/xen/configs/xenU_defconfig
linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig
linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile
linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/common.c
linux-2.6.10-xen-sparse/arch/xen/i386/kernel/entry.S
linux-2.6.10-xen-sparse/arch/xen/i386/kernel/head.S
linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c
linux-2.6.10-xen-sparse/arch/xen/i386/kernel/time.c
linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c
linux-2.6.10-xen-sparse/arch/xen/i386/mm/fault.c
linux-2.6.10-xen-sparse/arch/xen/i386/mm/hypervisor.c
linux-2.6.10-xen-sparse/arch/xen/kernel/Makefile
linux-2.6.10-xen-sparse/arch/xen/kernel/evtchn.c
linux-2.6.10-xen-sparse/drivers/xen/Makefile
linux-2.6.10-xen-sparse/drivers/xen/blkback/blkback.c
linux-2.6.10-xen-sparse/drivers/xen/blkfront/blkfront.c
linux-2.6.10-xen-sparse/drivers/xen/console/console.c
linux-2.6.10-xen-sparse/drivers/xen/evtchn/evtchn.c
linux-2.6.10-xen-sparse/drivers/xen/netback/netback.c
linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h
linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/processor.h
linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h
linux-2.6.10-xen-sparse/include/asm-xen/evtchn.h
linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h
linux-2.6.10-xen-sparse/include/asm-xen/multicall.h

diff --cc .rootkeys
index 2d02820ee3498595ea7e057a556e6c9de756c998,e80c251ef1314633f6011decd0ebc54133637058..f0894e1d743a9a354a24f3e8979d695cde729bc0
+++ b/.rootkeys
  3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.28-xen-sparse/mm/swapfile.c
  41180721bNns9Na7w1nJ0ZVt8bhUNA linux-2.4.28-xen-sparse/mm/vmalloc.c
  41505c57WAd5l1rlfCLNSCpx9J13vA linux-2.4.28-xen-sparse/net/core/skbuff.c
- 40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.9-xen-sparse/arch/xen/Kconfig
- 40f56237utH41NPukqHksuNf29IC9A linux-2.6.9-xen-sparse/arch/xen/Kconfig.drivers
- 40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.9-xen-sparse/arch/xen/Makefile
- 40f56237JTc60m1FRlUxkUaGSQKrNw linux-2.6.9-xen-sparse/arch/xen/boot/Makefile
- 40f56237hRxbacU_3PdoAl6DjZ3Jnw linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig
- 40f56237wubfjJKlfIzZlI3ZM2VgGA linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig
- 40f56237Mta0yHNaMS_qtM2rge0qYA linux-2.6.9-xen-sparse/arch/xen/i386/Kconfig
- 40f56238u2CJdXNpjsZgHBxeVyY-2g linux-2.6.9-xen-sparse/arch/xen/i386/Makefile
- 40f56238eczveJ86k_4hNxCLRQIF-g linux-2.6.9-xen-sparse/arch/xen/i386/kernel/Makefile
- 40f56238rXVTJQKbBuXXLH52qEArcg linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/Makefile
- 40f562385s4lr6Zg92gExe7UQ4A76Q linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/common.c
- 41ab440bnpxZdWShZrGgM9pPaz5rmA linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile
- 41ab440bBKWz-aEOEojU4PAMXe3Ppg linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c
- 40f56238XDtHSijkAFlbv1PT8Bhw_Q linux-2.6.9-xen-sparse/arch/xen/i386/kernel/entry.S
- 40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.9-xen-sparse/arch/xen/i386/kernel/head.S
- 40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.9-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c
- 40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.9-xen-sparse/arch/xen/i386/kernel/ioport.c
- 40f562382aC3_Gt4RG-4ZsfvDRUg3Q linux-2.6.9-xen-sparse/arch/xen/i386/kernel/irq.c
- 40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.9-xen-sparse/arch/xen/i386/kernel/ldt.c
- 4107adf1cNtsuOxOB4T6paAoY2R2PA linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c
- 40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.9-xen-sparse/arch/xen/i386/kernel/process.c
- 40f56238YQIJoYG2ehDGEcdTgLmGbg linux-2.6.9-xen-sparse/arch/xen/i386/kernel/setup.c
- 40f56238nWMQg7CKbyTy0KJNvCzbtg linux-2.6.9-xen-sparse/arch/xen/i386/kernel/signal.c
+ 40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.10-xen-sparse/arch/xen/Kconfig
+ 40f56237utH41NPukqHksuNf29IC9A linux-2.6.10-xen-sparse/arch/xen/Kconfig.drivers
+ 40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.10-xen-sparse/arch/xen/Makefile
+ 40f56237JTc60m1FRlUxkUaGSQKrNw linux-2.6.10-xen-sparse/arch/xen/boot/Makefile
+ 40f56237hRxbacU_3PdoAl6DjZ3Jnw linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig
+ 40f56237wubfjJKlfIzZlI3ZM2VgGA linux-2.6.10-xen-sparse/arch/xen/configs/xenU_defconfig
+ 40f56237Mta0yHNaMS_qtM2rge0qYA linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig
+ 40f56238u2CJdXNpjsZgHBxeVyY-2g linux-2.6.10-xen-sparse/arch/xen/i386/Makefile
+ 40f56238eczveJ86k_4hNxCLRQIF-g linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile
+ 40f56238rXVTJQKbBuXXLH52qEArcg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/Makefile
+ 40f562385s4lr6Zg92gExe7UQ4A76Q linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/common.c
+ 41ab440bnpxZdWShZrGgM9pPaz5rmA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile
+ 41ab440bBKWz-aEOEojU4PAMXe3Ppg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c
+ 40f56238XDtHSijkAFlbv1PT8Bhw_Q linux-2.6.10-xen-sparse/arch/xen/i386/kernel/entry.S
+ 40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.10-xen-sparse/arch/xen/i386/kernel/head.S
+ 40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c
+ 40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/ioport.c
+ 40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.10-xen-sparse/arch/xen/i386/kernel/ldt.c
+ 4107adf1cNtsuOxOB4T6paAoY2R2PA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/pci-dma.c
+ 40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c
+ 40f56238YQIJoYG2ehDGEcdTgLmGbg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c
+ 40f56238nWMQg7CKbyTy0KJNvCzbtg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/signal.c
+ 40f56238qVGkpO_ycnQA8k03kQzAgA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/time.c
+ 40f56238NzTgeO63RGoxHrW5NQeO3Q linux-2.6.10-xen-sparse/arch/xen/i386/kernel/timers/Makefile
+ 40f56238BMqG5PuSHufpjbvp_helBw linux-2.6.10-xen-sparse/arch/xen/i386/kernel/timers/timer_tsc.c
+ 40f562389xNa78YBZciUibQjyRU_Lg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c
+ 40f56238JypKAUG01ZojFwH7qnZ5uA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/vsyscall.S
+ 40f56238wi6AdNQjm0RT57bSkwb6hg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/vsyscall.lds
+ 40f56238a3w6-byOzexIlMgni76Lcg linux-2.6.10-xen-sparse/arch/xen/i386/mm/Makefile
+ 40f56238ILx8xlbywNbzTdv5Zr4xXQ linux-2.6.10-xen-sparse/arch/xen/i386/mm/fault.c
+ 4118cc35CbY8rfGVspF5O-7EkXBEAA linux-2.6.10-xen-sparse/arch/xen/i386/mm/highmem.c
+ 40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.10-xen-sparse/arch/xen/i386/mm/hypervisor.c
+ 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.10-xen-sparse/arch/xen/i386/mm/init.c
+ 41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.10-xen-sparse/arch/xen/i386/mm/ioremap.c
+ 413b5ab8LIowAnQrEmaOJSdmqm96jQ linux-2.6.10-xen-sparse/arch/xen/i386/mm/pageattr.c
+ 40f5623906UYHv1rsVUeRc0tFT0dWw linux-2.6.10-xen-sparse/arch/xen/i386/mm/pgtable.c
+ 4107adf12ndy94MidCaivDibJ3pPAg linux-2.6.10-xen-sparse/arch/xen/i386/pci/Makefile
+ 4107adf1WcCgkhsdLTRGX52cOG1vJg linux-2.6.10-xen-sparse/arch/xen/i386/pci/direct.c
+ 4107adf1s5u6249DNPUViX1YNagbUQ linux-2.6.10-xen-sparse/arch/xen/i386/pci/irq.c
+ 40f56239zOksGg_H4XD4ye6iZNtoZA linux-2.6.10-xen-sparse/arch/xen/kernel/Makefile
+ 40f56239bvOjuuuViZ0XMlNiREFC0A linux-2.6.10-xen-sparse/arch/xen/kernel/ctrl_if.c
+ 41ab6fa06JdF7jxUsuDcjN3UhuIAxg linux-2.6.10-xen-sparse/arch/xen/kernel/devmem.c
+ 40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.10-xen-sparse/arch/xen/kernel/evtchn.c
+ 4110f478aeQWllIN7J4kouAHiAqrPw linux-2.6.10-xen-sparse/arch/xen/kernel/fixup.c
+ 412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.10-xen-sparse/arch/xen/kernel/gnttab.c
+ 40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.10-xen-sparse/arch/xen/kernel/reboot.c
+ 414c113396tK1HTVeUalm3u-1DF16g linux-2.6.10-xen-sparse/arch/xen/kernel/skbuff.c
+ 3f68905c5eiA-lBMQSvXLMWS1ikDEA linux-2.6.10-xen-sparse/arch/xen/kernel/xen_proc.c
+ 41261688yS8eAyy-7kzG4KBs0xbYCA linux-2.6.10-xen-sparse/drivers/Makefile
+ 4108f5c1WfTIrs0HZFeV39sttekCTw linux-2.6.10-xen-sparse/drivers/char/mem.c
+ 4111308bZAIzwf_Kzu6x1TZYZ3E0_Q linux-2.6.10-xen-sparse/drivers/char/tty_io.c
+ 40f56239Dp_vMTgz8TEbvo1hjHGc3w linux-2.6.10-xen-sparse/drivers/xen/Makefile
+ 41768fbcncpBQf8s2l2-CwoSNIZ9uA linux-2.6.10-xen-sparse/drivers/xen/balloon/Makefile
+ 3e6377f8i5e9eGz7Pw6fQuhuTQ7DQg linux-2.6.10-xen-sparse/drivers/xen/balloon/balloon.c
+ 410d0893otFGghmv4dUXDUBBdY5aIA linux-2.6.10-xen-sparse/drivers/xen/blkback/Makefile
+ 4087cf0d1XgMkooTZAiJS6NrcpLQNQ linux-2.6.10-xen-sparse/drivers/xen/blkback/blkback.c
+ 4087cf0dZadZ8r6CEt4fNN350Yle3A linux-2.6.10-xen-sparse/drivers/xen/blkback/common.h
+ 4087cf0dxlh29iw0w-9rxOCEGCjPcw linux-2.6.10-xen-sparse/drivers/xen/blkback/control.c
+ 4087cf0dbuoH20fMjNZjcgrRK-1msQ linux-2.6.10-xen-sparse/drivers/xen/blkback/interface.c
+ 4087cf0dk97tacDzxfByWV7JifUYqA linux-2.6.10-xen-sparse/drivers/xen/blkback/vbd.c
+ 40f56239Sfle6wGv5FS0wjS_HI150A linux-2.6.10-xen-sparse/drivers/xen/blkfront/Kconfig
+ 40f562395atl9x4suKGhPkjqLOXESg linux-2.6.10-xen-sparse/drivers/xen/blkfront/Makefile
+ 40f56239-JNIaTzlviVJohVdoYOUpw linux-2.6.10-xen-sparse/drivers/xen/blkfront/blkfront.c
+ 40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.10-xen-sparse/drivers/xen/blkfront/block.h
+ 40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.10-xen-sparse/drivers/xen/blkfront/vbd.c
+ 40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.10-xen-sparse/drivers/xen/console/Makefile
+ 3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.10-xen-sparse/drivers/xen/console/console.c
+ 40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.10-xen-sparse/drivers/xen/evtchn/Makefile
+ 40f56239DoibTX6R-ZYd3QTXAB8_TA linux-2.6.10-xen-sparse/drivers/xen/evtchn/evtchn.c
+ 410a9817HEVJvred5Oy_uKH3HFJC5Q linux-2.6.10-xen-sparse/drivers/xen/netback/Makefile
+ 4097ba831lpGeLlPg-bfV8XarVVuoQ linux-2.6.10-xen-sparse/drivers/xen/netback/common.h
+ 4097ba83wvv8yi5P5xugCUBAdb6O-A linux-2.6.10-xen-sparse/drivers/xen/netback/control.c
+ 4097ba83byY5bTSugJGZ1exTxIcMKw linux-2.6.10-xen-sparse/drivers/xen/netback/interface.c
+ 4087cf0dGmSbFhFZyIZBJzvqxY-qBw linux-2.6.10-xen-sparse/drivers/xen/netback/netback.c
+ 40f56239lrg_Ob0BJ8WBFS1zeg2CYw linux-2.6.10-xen-sparse/drivers/xen/netfront/Kconfig
+ 40f56239Wd4k_ycG_mFsSO1r5xKdtQ linux-2.6.10-xen-sparse/drivers/xen/netfront/Makefile
+ 405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.6.10-xen-sparse/drivers/xen/netfront/netfront.c
+ 4108f5c1ppFXVpQzCOAZ6xXYubsjKA linux-2.6.10-xen-sparse/drivers/xen/privcmd/Makefile
+ 3e5a4e65IUfzzMu2kZFlGEB8-rpTaA linux-2.6.10-xen-sparse/drivers/xen/privcmd/privcmd.c
+ 412f47e4RKD-R5IS5gEXvcT8L4v8gA linux-2.6.10-xen-sparse/include/asm-generic/pgtable.h
+ 40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/desc.h
+ 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h
+ 40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/fixmap.h
+ 41979925z1MsKU1SfuuheM1IFDQ_bA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/floppy.h
+ 4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/highmem.h
+ 40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/io.h
+ 40f5623aKXkBBxgpLx2NcvkncQ1Yyw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
+ 40f5623aDMCsWOFO0jktZ4e8sjwvEg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
+ 40f5623arsFXkGdPvIqvFi3yFXGR0Q linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_pre.h
+ 4120f807GCO0uqsLqdZj9csxR1Wthw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mmu_context.h
 -40f5623aFTyFTR-vdiA-KaGxk5JOKQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/msr.h
+ 40f5623adgjZq9nAgCt0IXdWl7udSA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/page.h
+ 40f5623a54NuG-7qHihGYmw4wWQnMA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/param.h
+ 41137cc1kkvg0cg7uxddcEfjL7L67w linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pci.h
+ 40f5623atCokYc2uCysSJ8jFO8TEsw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgalloc.h
+ 412e01beTwiaC8sYY4XJP8PxLST5CA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level-defs.h
+ 40f5623aEToIXouJgO-ao5d5pcEt1w linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h
+ 40f5623aCCXRPlGpNthVXstGz9ZV3A linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable.h
+ 40f5623aPCkQQfPtJSooGdhcatrvnQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/processor.h
+ 412ea0afQL2CAI-f522TbLjLPMibPQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/ptrace.h
+ 40f5623bzLvxr7WoJIxVf2OH4rCBJg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/segment.h
+ 40f5623bG_LzgG6-qwk292nTc5Wabw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/setup.h
+ 40f5623bgzm_9vwxpzJswlAxg298Gg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/synch_bitops.h
+ 40f5623bVdKP7Dt7qm8twu3NcnGNbA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h
+ 40f5623bc8LKPRO09wY5dGDnY_YCpw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/tlbflush.h
+ 41062ab7uFxnCq-KtPeAm-aV8CicgA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/vga.h
+ 40f5623bxUbeGjkRrjDguCy_Gm8RLw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/xor.h
+ 41af4017PDMuSmMWtSRU5UC9Vylw5g linux-2.6.10-xen-sparse/include/asm-xen/balloon.h
+ 40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.10-xen-sparse/include/asm-xen/ctrl_if.h
+ 40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.10-xen-sparse/include/asm-xen/evtchn.h
+ 419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.10-xen-sparse/include/asm-xen/foreign_page.h
+ 412dfaeazclyNDM0cpnp60Yo4xulpQ linux-2.6.10-xen-sparse/include/asm-xen/gnttab.h
+ 40f5623aGPlsm0u1LTO-NVZ6AGzNRQ linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h
+ 3f108af1ylCIm82H052FVTfXACBHrw linux-2.6.10-xen-sparse/include/asm-xen/linux-public/privcmd.h
+ 3fa8e3f0kBLeE4To2vpdi3cpJbIkbQ linux-2.6.10-xen-sparse/include/asm-xen/linux-public/suspend.h
+ 40f5623cndVUFlkxpf7Lfx7xu8madQ linux-2.6.10-xen-sparse/include/asm-xen/multicall.h
+ 4122466356eIBnC9ot44WSVVIFyhQA linux-2.6.10-xen-sparse/include/asm-xen/queues.h
+ 3f689063BoW-HWV3auUJ-OqXfcGArw linux-2.6.10-xen-sparse/include/asm-xen/xen_proc.h
+ 419b4e93z2S0gR17XTy8wg09JEwAhg linux-2.6.10-xen-sparse/include/linux/gfp.h
+ 419dfc609zbti8rqL60tL2dHXQ_rvQ linux-2.6.10-xen-sparse/include/linux/irq.h
+ 4124f66f4NaKNa0xPiGGykn9QaZk3w linux-2.6.10-xen-sparse/include/linux/skbuff.h
+ 419dfc6awx7w88wk6cG9P3mPidX6LQ linux-2.6.10-xen-sparse/kernel/irq/manage.c
+ 40f56a0ddHCSs3501MY4hRf22tctOw linux-2.6.10-xen-sparse/mkbuildtree
+ 412f46c0LJuKAgSPGoC0Z1DEkLfuLA linux-2.6.10-xen-sparse/mm/memory.c
+ 410a94a4KT6I6X0LVc7djB39tRDp4g linux-2.6.10-xen-sparse/mm/page_alloc.c
+ 41505c572m-s9ATiO1LiD1GPznTTIg linux-2.6.10-xen-sparse/net/core/skbuff.c
 +41811cac4lkCB-fHir6CcxuEJ2pGsQ linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smp.c
 +41811ca9mbGpqBrZVrUGEiv8CTV3ng linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c
- 40f56238UL9uv78ODDzMwLL9yryeFw linux-2.6.9-xen-sparse/arch/xen/i386/kernel/sysenter.c
- 40f56238qVGkpO_ycnQA8k03kQzAgA linux-2.6.9-xen-sparse/arch/xen/i386/kernel/time.c
- 40f56238NzTgeO63RGoxHrW5NQeO3Q linux-2.6.9-xen-sparse/arch/xen/i386/kernel/timers/Makefile
- 40f56238BMqG5PuSHufpjbvp_helBw linux-2.6.9-xen-sparse/arch/xen/i386/kernel/timers/timer_tsc.c
- 40f562389xNa78YBZciUibQjyRU_Lg linux-2.6.9-xen-sparse/arch/xen/i386/kernel/traps.c
- 40f56238qASEI_IOhCKWNuwFKNZrKQ linux-2.6.9-xen-sparse/arch/xen/i386/kernel/vmlinux.lds.S
- 40f56238JypKAUG01ZojFwH7qnZ5uA linux-2.6.9-xen-sparse/arch/xen/i386/kernel/vsyscall.S
- 40f56238wi6AdNQjm0RT57bSkwb6hg linux-2.6.9-xen-sparse/arch/xen/i386/kernel/vsyscall.lds
- 40f56238a3w6-byOzexIlMgni76Lcg linux-2.6.9-xen-sparse/arch/xen/i386/mm/Makefile
- 40f56238ILx8xlbywNbzTdv5Zr4xXQ linux-2.6.9-xen-sparse/arch/xen/i386/mm/fault.c
- 4118cc35CbY8rfGVspF5O-7EkXBEAA linux-2.6.9-xen-sparse/arch/xen/i386/mm/highmem.c
- 40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c
- 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.9-xen-sparse/arch/xen/i386/mm/init.c
- 41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.9-xen-sparse/arch/xen/i386/mm/ioremap.c
- 413b5ab8LIowAnQrEmaOJSdmqm96jQ linux-2.6.9-xen-sparse/arch/xen/i386/mm/pageattr.c
- 40f5623906UYHv1rsVUeRc0tFT0dWw linux-2.6.9-xen-sparse/arch/xen/i386/mm/pgtable.c
- 4107adf12ndy94MidCaivDibJ3pPAg linux-2.6.9-xen-sparse/arch/xen/i386/pci/Makefile
- 4107adf1WcCgkhsdLTRGX52cOG1vJg linux-2.6.9-xen-sparse/arch/xen/i386/pci/direct.c
- 4107adf1s5u6249DNPUViX1YNagbUQ linux-2.6.9-xen-sparse/arch/xen/i386/pci/irq.c
- 40f56239zOksGg_H4XD4ye6iZNtoZA linux-2.6.9-xen-sparse/arch/xen/kernel/Makefile
- 40f56239bvOjuuuViZ0XMlNiREFC0A linux-2.6.9-xen-sparse/arch/xen/kernel/ctrl_if.c
- 41ab6fa06JdF7jxUsuDcjN3UhuIAxg linux-2.6.9-xen-sparse/arch/xen/kernel/devmem.c
- 40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c
- 4110f478aeQWllIN7J4kouAHiAqrPw linux-2.6.9-xen-sparse/arch/xen/kernel/fixup.c
- 412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.9-xen-sparse/arch/xen/kernel/gnttab.c
- 40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.9-xen-sparse/arch/xen/kernel/reboot.c
- 414c113396tK1HTVeUalm3u-1DF16g linux-2.6.9-xen-sparse/arch/xen/kernel/skbuff.c
 +418f90e4lGdeJK9rmbOB1kN-IKSjsQ linux-2.6.9-xen-sparse/arch/xen/kernel/smp.c
- 3f68905c5eiA-lBMQSvXLMWS1ikDEA linux-2.6.9-xen-sparse/arch/xen/kernel/xen_proc.c
- 41261688yS8eAyy-7kzG4KBs0xbYCA linux-2.6.9-xen-sparse/drivers/Makefile
- 4108f5c1WfTIrs0HZFeV39sttekCTw linux-2.6.9-xen-sparse/drivers/char/mem.c
- 4111308bZAIzwf_Kzu6x1TZYZ3E0_Q linux-2.6.9-xen-sparse/drivers/char/tty_io.c
- 40f56239Dp_vMTgz8TEbvo1hjHGc3w linux-2.6.9-xen-sparse/drivers/xen/Makefile
- 41768fbcncpBQf8s2l2-CwoSNIZ9uA linux-2.6.9-xen-sparse/drivers/xen/balloon/Makefile
- 3e6377f8i5e9eGz7Pw6fQuhuTQ7DQg linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c
- 410d0893otFGghmv4dUXDUBBdY5aIA linux-2.6.9-xen-sparse/drivers/xen/blkback/Makefile
- 4087cf0d1XgMkooTZAiJS6NrcpLQNQ linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c
- 4087cf0dZadZ8r6CEt4fNN350Yle3A linux-2.6.9-xen-sparse/drivers/xen/blkback/common.h
- 4087cf0dxlh29iw0w-9rxOCEGCjPcw linux-2.6.9-xen-sparse/drivers/xen/blkback/control.c
- 4087cf0dbuoH20fMjNZjcgrRK-1msQ linux-2.6.9-xen-sparse/drivers/xen/blkback/interface.c
- 4087cf0dk97tacDzxfByWV7JifUYqA linux-2.6.9-xen-sparse/drivers/xen/blkback/vbd.c
- 40f56239Sfle6wGv5FS0wjS_HI150A linux-2.6.9-xen-sparse/drivers/xen/blkfront/Kconfig
- 40f562395atl9x4suKGhPkjqLOXESg linux-2.6.9-xen-sparse/drivers/xen/blkfront/Makefile
- 40f56239-JNIaTzlviVJohVdoYOUpw linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c
- 40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.9-xen-sparse/drivers/xen/blkfront/block.h
- 40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.9-xen-sparse/drivers/xen/blkfront/vbd.c
 +41a226e0vjAcDXHOnXE5ummcdUD2mg linux-2.6.9-xen-sparse/drivers/xen/blktap/Makefile
 +41a226e0VeZA1N8tbU6nvJ3OxUcJmw linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.c
 +41a226e1k4J5VMLnrYXDWRqElS49YQ linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.h
 +41a226e1-A_Hy7utS8vJKaXnH_tzfA linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c
 +41a226e19NoUUTOvs7jumDMRYDIO4Q linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_datapath.c
 +41a226e1MNSyWWK5dEVgvSQ5OW0fDA linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_userdev.c
- 40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.9-xen-sparse/drivers/xen/console/Makefile
- 3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.9-xen-sparse/drivers/xen/console/console.c
- 40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.9-xen-sparse/drivers/xen/evtchn/Makefile
- 40f56239DoibTX6R-ZYd3QTXAB8_TA linux-2.6.9-xen-sparse/drivers/xen/evtchn/evtchn.c
- 410a9817HEVJvred5Oy_uKH3HFJC5Q linux-2.6.9-xen-sparse/drivers/xen/netback/Makefile
- 4097ba831lpGeLlPg-bfV8XarVVuoQ linux-2.6.9-xen-sparse/drivers/xen/netback/common.h
- 4097ba83wvv8yi5P5xugCUBAdb6O-A linux-2.6.9-xen-sparse/drivers/xen/netback/control.c
- 4097ba83byY5bTSugJGZ1exTxIcMKw linux-2.6.9-xen-sparse/drivers/xen/netback/interface.c
- 4087cf0dGmSbFhFZyIZBJzvqxY-qBw linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c
- 40f56239lrg_Ob0BJ8WBFS1zeg2CYw linux-2.6.9-xen-sparse/drivers/xen/netfront/Kconfig
- 40f56239Wd4k_ycG_mFsSO1r5xKdtQ linux-2.6.9-xen-sparse/drivers/xen/netfront/Makefile
- 405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c
- 4108f5c1ppFXVpQzCOAZ6xXYubsjKA linux-2.6.9-xen-sparse/drivers/xen/privcmd/Makefile
- 3e5a4e65IUfzzMu2kZFlGEB8-rpTaA linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c
- 412f47e4RKD-R5IS5gEXvcT8L4v8gA linux-2.6.9-xen-sparse/include/asm-generic/pgtable.h
- 40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/desc.h
- 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h
- 40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/fixmap.h
- 41979925z1MsKU1SfuuheM1IFDQ_bA linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/floppy.h
 +41a64cdeQ5SWVEVbSZ0K-IeHHhIJ_w linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/hardirq.h
- 4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/highmem.h
- 40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/io.h
- 40f5623aKXkBBxgpLx2NcvkncQ1Yyw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
- 40f5623aDMCsWOFO0jktZ4e8sjwvEg linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
- 40f5623arsFXkGdPvIqvFi3yFXGR0Q linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_pre.h
 +41811f07Iri9hrvs97t-baxmhOwWDQ linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h
- 4120f807GCO0uqsLqdZj9csxR1Wthw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mmu_context.h
- 40f5623adgjZq9nAgCt0IXdWl7udSA linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/page.h
- 40f5623a54NuG-7qHihGYmw4wWQnMA linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/param.h
- 41137cc1kkvg0cg7uxddcEfjL7L67w linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pci.h
- 40f5623atCokYc2uCysSJ8jFO8TEsw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgalloc.h
- 412e01beTwiaC8sYY4XJP8PxLST5CA linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable-2level-defs.h
- 40f5623aEToIXouJgO-ao5d5pcEt1w linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h
- 40f5623aCCXRPlGpNthVXstGz9ZV3A linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h
- 40f5623aPCkQQfPtJSooGdhcatrvnQ linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/processor.h
- 412ea0afQL2CAI-f522TbLjLPMibPQ linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/ptrace.h
- 40f5623bzLvxr7WoJIxVf2OH4rCBJg linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/segment.h
- 40f5623bG_LzgG6-qwk292nTc5Wabw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/setup.h
 +4198c32a8NzmcKVOzKaEJfaQxxiA0A linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/spinlock.h
- 40f5623bgzm_9vwxpzJswlAxg298Gg linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/synch_bitops.h
- 40f5623bVdKP7Dt7qm8twu3NcnGNbA linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/system.h
- 40f5623bc8LKPRO09wY5dGDnY_YCpw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/tlbflush.h
- 41062ab7uFxnCq-KtPeAm-aV8CicgA linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/vga.h
- 40f5623bxUbeGjkRrjDguCy_Gm8RLw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/xor.h
- 41af4017PDMuSmMWtSRU5UC9Vylw5g linux-2.6.9-xen-sparse/include/asm-xen/balloon.h
- 40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.9-xen-sparse/include/asm-xen/ctrl_if.h
- 40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h
- 419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.9-xen-sparse/include/asm-xen/foreign_page.h
- 412dfaeazclyNDM0cpnp60Yo4xulpQ linux-2.6.9-xen-sparse/include/asm-xen/gnttab.h
- 40f5623aGPlsm0u1LTO-NVZ6AGzNRQ linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h
- 3f108af1ylCIm82H052FVTfXACBHrw linux-2.6.9-xen-sparse/include/asm-xen/linux-public/privcmd.h
- 3fa8e3f0kBLeE4To2vpdi3cpJbIkbQ linux-2.6.9-xen-sparse/include/asm-xen/linux-public/suspend.h
- 40f5623cndVUFlkxpf7Lfx7xu8madQ linux-2.6.9-xen-sparse/include/asm-xen/multicall.h
- 4122466356eIBnC9ot44WSVVIFyhQA linux-2.6.9-xen-sparse/include/asm-xen/queues.h
- 3f689063BoW-HWV3auUJ-OqXfcGArw linux-2.6.9-xen-sparse/include/asm-xen/xen_proc.h
- 4124d8c4aocX7A-jIbuGraWN84pxGQ linux-2.6.9-xen-sparse/include/linux/bio.h
- 419b4e93z2S0gR17XTy8wg09JEwAhg linux-2.6.9-xen-sparse/include/linux/gfp.h
- 4124f66f4NaKNa0xPiGGykn9QaZk3w linux-2.6.9-xen-sparse/include/linux/skbuff.h
- 40f56a0ddHCSs3501MY4hRf22tctOw linux-2.6.9-xen-sparse/mkbuildtree
- 412f46c0LJuKAgSPGoC0Z1DEkLfuLA linux-2.6.9-xen-sparse/mm/memory.c
- 410a94a4KT6I6X0LVc7djB39tRDp4g linux-2.6.9-xen-sparse/mm/page_alloc.c
- 41505c572m-s9ATiO1LiD1GPznTTIg linux-2.6.9-xen-sparse/net/core/skbuff.c
- 4149ec79wMpIHdvbntxqVGLRZZjPxw linux-2.6.9-xen-sparse/net/ipv4/raw.c
  413cb1e4zst25MDYjg63Y-NGC5_pLg netbsd-2.0-xen-sparse/Makefile
  413cb1e5c_Mkxf_X0zimEhTKI_l4DA netbsd-2.0-xen-sparse/mkbuildtree
  413cb1e5kY_Zil7-b0kI6hvCIxBEYg netbsd-2.0-xen-sparse/nbconfig-xen
index 0000000000000000000000000000000000000000,13b3d1fed62294729610c888738afb55d17f77dd..6d78869bece8f9f46fe35697211b46dc8fcef03e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,166 +1,190 @@@
+ #
+ # For a description of the syntax of this configuration file,
+ # see Documentation/kbuild/kconfig-language.txt.
+ #
+ mainmenu "Linux Kernel Configuration"
+ config XEN
+       bool
+       default y
+       help
+         This is the Linux Xen port.
+ config ARCH_XEN
+       bool
+       default y
+ config NO_IDLE_HZ
+       bool
+       default y
+ menu "XEN"
+ config XEN_PRIVILEGED_GUEST
+       bool "Privileged Guest (domain 0)"
+       default n
+         select XEN_PHYSDEV_ACCESS
+       help
+         Support for privileged operation (domain 0)
+ config XEN_PHYSDEV_ACCESS
+       bool "Physical device access"
+       default y if XEN_PRIVILEGED_GUEST
+       default n if !XEN_PRIVILEGED_GUEST
+       help
+         Assume access is available to physical hardware devices
+           (e.g., hard drives, network cards). This allows you to configure
+           such devices and also includes some low-level support that is
+           otherwise not compiled into the kernel.
+ config XEN_BLKDEV_BACKEND
+         bool "Block-device backend driver"
+         default y if XEN_PHYSDEV_ACCESS
+         default n if !XEN_PHYSDEV_ACCESS
+         help
+           The block-device backend driver allows the kernel to export its
+           block devices to other guests via a high-performance shared-memory
+           interface.
++if XEN_BLKDEV_BACKEND
++config XEN_BLKDEV_TAP_BE
++        bool "Block Tap support for backend driver (DANGEROUS)"
++        default n
++        help
++          If you intend to use the block tap driver, the backend domain will
++          not know the domain id of the real frontend, and so will not be able
++          to map its data pages.  This modifies the backend to attempt to map
++          from both the tap domain and the real frontend.  This presents a
++          security risk, and so should ONLY be used for development
++          with the blktap.  This option will be removed as the block drivers are
++          modified to use grant tables.
++endif
++
+ config XEN_NETDEV_BACKEND
+         bool "Network-device backend driver"
+         default y if XEN_PHYSDEV_ACCESS
+         default n if !XEN_PHYSDEV_ACCESS
+         help
+           The network-device backend driver allows the kernel to export its
+           network devices to other guests via a high-performance shared-memory
+           interface.
+ config XEN_BLKDEV_FRONTEND
+         bool "Block-device frontend driver"
+         default y
+         help
+           The block-device frontend driver allows the kernel to access block
+           devices mounted within another guest OS. Unless you are building a
+           dedicated device-driver domain, or your master control domain
+           (domain 0), then you almost certainly want to say Y here.
+ config XEN_NETDEV_FRONTEND
+         bool "Network-device frontend driver"
+         default y
+         help
+           The network-device frontend driver allows the kernel to access
+           network interfaces within another guest OS. Unless you are building a
+           dedicated device-driver domain, or your master control domain
+           (domain 0), then you almost certainly want to say Y here.
+ if XEN_NETDEV_FRONTEND
+ config XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER
+         bool "Pipelined transmitter (DANGEROUS)"
+         default n
+         help
+           The driver will assume that the backend is pipelining packets for
+           transmission: whenever packets are pending in the remote backend,
+           the driver will not send asynchronous notifications when it queues
+           additional packets for transmission.
+           If the backend is a dumb domain, such as a transparent Ethernet
+           bridge with no local IP interface, it is safe to say Y here to get
+           slightly lower network overhead.
+           If the backend has a local IP interface; or may be doing smart things
+           like reassembling packets to perform firewall filtering; or if you
+           are unsure; or if you experience network hangs when this option is
+           enabled; then you must say N here.
+ endif
++config XEN_BLKDEV_TAP
++        bool "Block device tap driver"
++        default n
++        help
++          This driver allows a VM to interact on block device channels
++          to other VMs.  Block messages may be passed through or redirected
++          to a character device, allowing device prototyping in application
++          space.  Odds are that you want to say N here.
++
++
+ config XEN_WRITABLE_PAGETABLES
+       bool
+       default y
+ config XEN_SCRUB_PAGES
+         bool "Scrub memory before freeing it to Xen"
+         default y
+         help
+           Erase memory contents before freeing it back to Xen's global
+           pool. This ensures that any secrets contained within that
+           memory (e.g., private keys) cannot be found by other guests that
+           may be running on the machine. Most people will want to say Y here.
+           If security is not a concern then you may increase performance by
+           saying N.
+ endmenu
+ config HAVE_ARCH_DEV_ALLOC_SKB
+       bool
+       default y
+ #config VT
+ #     bool
+ #     default y
+ #config VT_CONSOLE
+ #     bool
+ #     default y
+ #config HW_CONSOLE
+ #     bool
+ #     default y
+ choice
+       prompt "Processor Type"
+       default X86
+ config X86
+       bool "X86"
+       help
+         Choose this option if your computer is a X86 architecture.
+ config X86_64
+       bool "X86_64"
+       help
+         Choose this option if your computer is a X86 architecture.
+ endchoice
+ source "init/Kconfig"
+ if X86
+ source "arch/xen/i386/Kconfig"
+ endif
+ menu "Executable file formats"
+ source "fs/Kconfig.binfmt"
+ endmenu
+ source "arch/xen/Kconfig.drivers"
+ source "fs/Kconfig"
+ source "security/Kconfig"
+ source "crypto/Kconfig"
+ source "lib/Kconfig"
index 0000000000000000000000000000000000000000,6f7872ea71ca1b5e511d2ec90b94add2740e62b4..ebf3df11ea8e34f0197ba6424f9b7c99d2f0e817
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1055 +1,1057 @@@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.10-rc3-xen0
+ # Sun Dec 26 10:34:29 2004
+ #
+ CONFIG_XEN=y
+ CONFIG_ARCH_XEN=y
+ CONFIG_NO_IDLE_HZ=y
+ #
+ # XEN
+ #
+ CONFIG_XEN_PRIVILEGED_GUEST=y
+ CONFIG_XEN_PHYSDEV_ACCESS=y
+ CONFIG_XEN_BLKDEV_BACKEND=y
++# CONFIG_XEN_BLKDEV_TAP_BE is not set
+ CONFIG_XEN_NETDEV_BACKEND=y
+ CONFIG_XEN_BLKDEV_FRONTEND=y
+ CONFIG_XEN_NETDEV_FRONTEND=y
++# CONFIG_XEN_BLKDEV_TAP is not set
+ # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
+ CONFIG_XEN_WRITABLE_PAGETABLES=y
+ CONFIG_XEN_SCRUB_PAGES=y
+ CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+ CONFIG_X86=y
+ # CONFIG_X86_64 is not set
+ #
+ # Code maturity level options
+ #
+ CONFIG_EXPERIMENTAL=y
+ # CONFIG_CLEAN_COMPILE is not set
+ CONFIG_BROKEN=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_LOCK_KERNEL=y
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ CONFIG_SYSCTL=y
+ # CONFIG_AUDIT is not set
+ CONFIG_LOG_BUF_SHIFT=14
+ CONFIG_HOTPLUG=y
+ CONFIG_KOBJECT_UEVENT=y
+ # CONFIG_IKCONFIG is not set
+ # CONFIG_EMBEDDED is not set
+ CONFIG_KALLSYMS=y
+ # CONFIG_KALLSYMS_ALL is not set
+ # CONFIG_KALLSYMS_EXTRA_PASS is not set
+ CONFIG_FUTEX=y
+ CONFIG_EPOLL=y
+ # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+ CONFIG_SHMEM=y
+ CONFIG_CC_ALIGN_FUNCTIONS=0
+ CONFIG_CC_ALIGN_LABELS=0
+ CONFIG_CC_ALIGN_LOOPS=0
+ CONFIG_CC_ALIGN_JUMPS=0
+ # CONFIG_TINY_SHMEM is not set
+ #
+ # Loadable module support
+ #
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+ CONFIG_OBSOLETE_MODPARM=y
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+ #
+ # X86 Processor Configuration
+ #
+ CONFIG_XENARCH="i386"
+ CONFIG_MMU=y
+ CONFIG_UID16=y
+ CONFIG_GENERIC_ISA_DMA=y
+ CONFIG_GENERIC_IOMAP=y
+ # CONFIG_M386 is not set
+ # CONFIG_M486 is not set
+ # CONFIG_M586 is not set
+ # CONFIG_M586TSC is not set
+ # CONFIG_M586MMX is not set
+ # CONFIG_M686 is not set
+ # CONFIG_MPENTIUMII is not set
+ # CONFIG_MPENTIUMIII is not set
+ # CONFIG_MPENTIUMM is not set
+ CONFIG_MPENTIUM4=y
+ # CONFIG_MK6 is not set
+ # CONFIG_MK7 is not set
+ # CONFIG_MK8 is not set
+ # CONFIG_MCRUSOE is not set
+ # CONFIG_MEFFICEON is not set
+ # CONFIG_MWINCHIPC6 is not set
+ # CONFIG_MWINCHIP2 is not set
+ # CONFIG_MWINCHIP3D is not set
+ # CONFIG_MCYRIXIII is not set
+ # CONFIG_MVIAC3_2 is not set
+ # CONFIG_X86_GENERIC is not set
+ CONFIG_X86_CMPXCHG=y
+ CONFIG_X86_XADD=y
+ CONFIG_X86_L1_CACHE_SHIFT=7
+ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+ CONFIG_X86_WP_WORKS_OK=y
+ CONFIG_X86_INVLPG=y
+ CONFIG_X86_BSWAP=y
+ CONFIG_X86_POPAD_OK=y
+ CONFIG_X86_GOOD_APIC=y
+ CONFIG_X86_INTEL_USERCOPY=y
+ CONFIG_X86_USE_PPRO_CHECKSUM=y
+ # CONFIG_HPET_TIMER is not set
+ # CONFIG_HPET_EMULATE_RTC is not set
+ # CONFIG_SMP is not set
+ CONFIG_PREEMPT=y
+ CONFIG_X86_CPUID=y
+ #
+ # Firmware Drivers
+ #
+ # CONFIG_EDD is not set
+ CONFIG_NOHIGHMEM=y
+ # CONFIG_HIGHMEM4G is not set
+ CONFIG_MTRR=y
+ CONFIG_HAVE_DEC_LOCK=y
+ # CONFIG_REGPARM is not set
+ #
+ # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+ #
+ CONFIG_PCI=y
+ CONFIG_PCI_DIRECT=y
+ CONFIG_PCI_LEGACY_PROC=y
+ # CONFIG_PCI_NAMES is not set
+ CONFIG_ISA=y
+ # CONFIG_EISA is not set
+ # CONFIG_MCA is not set
+ # CONFIG_SCx200 is not set
+ #
+ # PCCARD (PCMCIA/CardBus) support
+ #
+ # CONFIG_PCCARD is not set
+ #
+ # PC-card bridges
+ #
+ CONFIG_PCMCIA_PROBE=y
+ #
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+ #
+ # Kernel hacking
+ #
+ CONFIG_DEBUG_KERNEL=y
+ CONFIG_EARLY_PRINTK=y
+ # CONFIG_DEBUG_STACKOVERFLOW is not set
+ # CONFIG_DEBUG_STACK_USAGE is not set
+ CONFIG_DEBUG_SLAB=y
+ CONFIG_MAGIC_SYSRQ=y
+ # CONFIG_DEBUG_SPINLOCK is not set
+ CONFIG_DEBUG_PAGEALLOC=y
+ # CONFIG_DEBUG_INFO is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_FRAME_POINTER is not set
+ # CONFIG_4KSTACKS is not set
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_X86_BIOS_REBOOT=y
+ CONFIG_PC=y
+ #
+ # Executable file formats
+ #
+ CONFIG_BINFMT_ELF=y
+ # CONFIG_BINFMT_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+ #
+ # Device Drivers
+ #
+ #
+ # Generic Driver Options
+ #
+ # CONFIG_STANDALONE is not set
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_DEBUG_DRIVER is not set
+ #
+ # Memory Technology Devices (MTD)
+ #
+ # CONFIG_MTD is not set
+ #
+ # Parallel port support
+ #
+ # CONFIG_PARPORT is not set
+ #
+ # Plug and Play support
+ #
+ # CONFIG_PNP is not set
+ #
+ # Block devices
+ #
+ CONFIG_BLK_DEV_FD=y
+ # CONFIG_BLK_DEV_XD is not set
+ # CONFIG_BLK_CPQ_DA is not set
+ CONFIG_BLK_CPQ_CISS_DA=y
+ # CONFIG_CISS_SCSI_TAPE is not set
+ # CONFIG_BLK_DEV_DAC960 is not set
+ # CONFIG_BLK_DEV_UMEM is not set
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+ # CONFIG_BLK_DEV_NBD is not set
+ # CONFIG_BLK_DEV_SX8 is not set
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=4096
+ CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ # CONFIG_LBD is not set
+ # CONFIG_CDROM_PKTCDVD is not set
+ #
+ # IO Schedulers
+ #
+ CONFIG_IOSCHED_NOOP=y
+ CONFIG_IOSCHED_AS=y
+ CONFIG_IOSCHED_DEADLINE=y
+ CONFIG_IOSCHED_CFQ=y
+ #
+ # ATA/ATAPI/MFM/RLL support
+ #
+ CONFIG_IDE=y
+ CONFIG_BLK_DEV_IDE=y
+ #
+ # Please see Documentation/ide.txt for help/info on IDE drives
+ #
+ # CONFIG_BLK_DEV_IDE_SATA is not set
+ # CONFIG_BLK_DEV_HD_IDE is not set
+ CONFIG_BLK_DEV_IDEDISK=y
+ # CONFIG_IDEDISK_MULTI_MODE is not set
+ CONFIG_BLK_DEV_IDECD=y
+ # CONFIG_BLK_DEV_IDETAPE is not set
+ # CONFIG_BLK_DEV_IDEFLOPPY is not set
+ # CONFIG_BLK_DEV_IDESCSI is not set
+ # CONFIG_IDE_TASK_IOCTL is not set
+ #
+ # IDE chipset support/bugfixes
+ #
+ CONFIG_IDE_GENERIC=y
+ # CONFIG_BLK_DEV_CMD640 is not set
+ CONFIG_BLK_DEV_IDEPCI=y
+ # CONFIG_IDEPCI_SHARE_IRQ is not set
+ # CONFIG_BLK_DEV_OFFBOARD is not set
+ CONFIG_BLK_DEV_GENERIC=y
+ # CONFIG_BLK_DEV_OPTI621 is not set
+ # CONFIG_BLK_DEV_RZ1000 is not set
+ CONFIG_BLK_DEV_IDEDMA_PCI=y
+ # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+ CONFIG_IDEDMA_PCI_AUTO=y
+ # CONFIG_IDEDMA_ONLYDISK is not set
+ # CONFIG_BLK_DEV_AEC62XX is not set
+ # CONFIG_BLK_DEV_ALI15X3 is not set
+ # CONFIG_BLK_DEV_AMD74XX is not set
+ # CONFIG_BLK_DEV_ATIIXP is not set
+ # CONFIG_BLK_DEV_CMD64X is not set
+ # CONFIG_BLK_DEV_TRIFLEX is not set
+ # CONFIG_BLK_DEV_CY82C693 is not set
+ # CONFIG_BLK_DEV_CS5520 is not set
+ # CONFIG_BLK_DEV_CS5530 is not set
+ # CONFIG_BLK_DEV_HPT34X is not set
+ # CONFIG_BLK_DEV_HPT366 is not set
+ # CONFIG_BLK_DEV_SC1200 is not set
+ CONFIG_BLK_DEV_PIIX=y
+ # CONFIG_BLK_DEV_NS87415 is not set
+ # CONFIG_BLK_DEV_PDC202XX_OLD is not set
+ # CONFIG_BLK_DEV_PDC202XX_NEW is not set
+ CONFIG_BLK_DEV_SVWKS=y
+ # CONFIG_BLK_DEV_SIIMAGE is not set
+ # CONFIG_BLK_DEV_SIS5513 is not set
+ # CONFIG_BLK_DEV_SLC90E66 is not set
+ # CONFIG_BLK_DEV_TRM290 is not set
+ # CONFIG_BLK_DEV_VIA82CXXX is not set
+ # CONFIG_IDE_ARM is not set
+ # CONFIG_IDE_CHIPSETS is not set
+ CONFIG_BLK_DEV_IDEDMA=y
+ # CONFIG_IDEDMA_IVB is not set
+ CONFIG_IDEDMA_AUTO=y
+ # CONFIG_BLK_DEV_HD is not set
+ #
+ # SCSI device support
+ #
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+ #
+ # SCSI support type (disk, tape, CD-ROM)
+ #
+ CONFIG_BLK_DEV_SD=y
+ # CONFIG_CHR_DEV_ST is not set
+ # CONFIG_CHR_DEV_OSST is not set
+ # CONFIG_BLK_DEV_SR is not set
+ # CONFIG_CHR_DEV_SG is not set
+ #
+ # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+ #
+ # CONFIG_SCSI_MULTI_LUN is not set
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+ #
+ # SCSI Transport Attributes
+ #
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ #
+ # SCSI low-level drivers
+ #
+ CONFIG_BLK_DEV_3W_XXXX_RAID=y
+ # CONFIG_SCSI_3W_9XXX is not set
+ # CONFIG_SCSI_7000FASST is not set
+ # CONFIG_SCSI_ACARD is not set
+ # CONFIG_SCSI_AHA152X is not set
+ # CONFIG_SCSI_AHA1542 is not set
+ CONFIG_SCSI_AACRAID=y
+ CONFIG_SCSI_AIC7XXX=y
+ CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+ CONFIG_AIC7XXX_DEBUG_ENABLE=y
+ CONFIG_AIC7XXX_DEBUG_MASK=0
+ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+ # CONFIG_SCSI_AIC7XXX_OLD is not set
+ CONFIG_SCSI_AIC79XX=y
+ CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+ CONFIG_AIC79XX_RESET_DELAY_MS=15000
+ # CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+ CONFIG_AIC79XX_DEBUG_ENABLE=y
+ CONFIG_AIC79XX_DEBUG_MASK=0
+ CONFIG_AIC79XX_REG_PRETTY_PRINT=y
+ # CONFIG_SCSI_DPT_I2O is not set
+ # CONFIG_SCSI_ADVANSYS is not set
+ # CONFIG_SCSI_IN2000 is not set
+ # CONFIG_MEGARAID_NEWGEN is not set
+ # CONFIG_MEGARAID_LEGACY is not set
+ CONFIG_SCSI_SATA=y
+ # CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ CONFIG_SCSI_ATA_PIIX=y
+ # CONFIG_SCSI_SATA_NV is not set
+ CONFIG_SCSI_SATA_PROMISE=y
+ CONFIG_SCSI_SATA_SX4=y
+ CONFIG_SCSI_SATA_SIL=y
+ # CONFIG_SCSI_SATA_SIS is not set
+ # CONFIG_SCSI_SATA_ULI is not set
+ # CONFIG_SCSI_SATA_VIA is not set
+ # CONFIG_SCSI_SATA_VITESSE is not set
+ CONFIG_SCSI_BUSLOGIC=y
+ # CONFIG_SCSI_OMIT_FLASHPOINT is not set
+ # CONFIG_SCSI_CPQFCTS is not set
+ # CONFIG_SCSI_DMX3191D is not set
+ # CONFIG_SCSI_DTC3280 is not set
+ # CONFIG_SCSI_EATA is not set
+ # CONFIG_SCSI_EATA_PIO is not set
+ # CONFIG_SCSI_FUTURE_DOMAIN is not set
+ # CONFIG_SCSI_GDTH is not set
+ # CONFIG_SCSI_GENERIC_NCR5380 is not set
+ # CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+ # CONFIG_SCSI_IPS is not set
+ # CONFIG_SCSI_INITIO is not set
+ # CONFIG_SCSI_INIA100 is not set
+ # CONFIG_SCSI_NCR53C406A is not set
+ # CONFIG_SCSI_SYM53C8XX_2 is not set
+ # CONFIG_SCSI_IPR is not set
+ # CONFIG_SCSI_PAS16 is not set
+ # CONFIG_SCSI_PCI2000 is not set
+ # CONFIG_SCSI_PCI2220I is not set
+ # CONFIG_SCSI_PSI240I is not set
+ # CONFIG_SCSI_QLOGIC_FAS is not set
+ # CONFIG_SCSI_QLOGIC_ISP is not set
+ # CONFIG_SCSI_QLOGIC_FC is not set
+ # CONFIG_SCSI_QLOGIC_1280 is not set
+ CONFIG_SCSI_QLA2XXX=y
+ # CONFIG_SCSI_QLA21XX is not set
+ # CONFIG_SCSI_QLA22XX is not set
+ # CONFIG_SCSI_QLA2300 is not set
+ # CONFIG_SCSI_QLA2322 is not set
+ # CONFIG_SCSI_QLA6312 is not set
+ # CONFIG_SCSI_QLA6322 is not set
+ # CONFIG_SCSI_SEAGATE is not set
+ # CONFIG_SCSI_SYM53C416 is not set
+ # CONFIG_SCSI_DC395x is not set
+ # CONFIG_SCSI_DC390T is not set
+ # CONFIG_SCSI_T128 is not set
+ # CONFIG_SCSI_U14_34F is not set
+ # CONFIG_SCSI_ULTRASTOR is not set
+ # CONFIG_SCSI_NSP32 is not set
+ # CONFIG_SCSI_DEBUG is not set
+ #
+ # Old CD-ROM drivers (not SCSI, not IDE)
+ #
+ # CONFIG_CD_NO_IDESCSI is not set
+ #
+ # Multi-device support (RAID and LVM)
+ #
+ CONFIG_MD=y
+ CONFIG_BLK_DEV_MD=y
+ # CONFIG_MD_LINEAR is not set
+ CONFIG_MD_RAID0=y
+ CONFIG_MD_RAID1=y
+ # CONFIG_MD_RAID10 is not set
+ CONFIG_MD_RAID5=y
+ # CONFIG_MD_RAID6 is not set
+ # CONFIG_MD_MULTIPATH is not set
+ # CONFIG_MD_FAULTY is not set
+ CONFIG_BLK_DEV_DM=y
+ # CONFIG_DM_CRYPT is not set
+ CONFIG_DM_SNAPSHOT=y
+ CONFIG_DM_MIRROR=y
+ # CONFIG_DM_ZERO is not set
+ #
+ # Fusion MPT device support
+ #
+ # CONFIG_FUSION is not set
+ #
+ # IEEE 1394 (FireWire) support
+ #
+ # CONFIG_IEEE1394 is not set
+ #
+ # I2O device support
+ #
+ # CONFIG_I2O is not set
+ #
+ # Networking support
+ #
+ CONFIG_NET=y
+ #
+ # Networking options
+ #
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ # CONFIG_NETLINK_DEV is not set
+ CONFIG_UNIX=y
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+ # CONFIG_IP_ADVANCED_ROUTER is not set
+ CONFIG_IP_PNP=y
+ CONFIG_IP_PNP_DHCP=y
+ # CONFIG_IP_PNP_BOOTP is not set
+ # CONFIG_IP_PNP_RARP is not set
+ # CONFIG_NET_IPIP is not set
+ # CONFIG_NET_IPGRE is not set
+ # CONFIG_ARPD is not set
+ # CONFIG_SYN_COOKIES is not set
+ # CONFIG_INET_AH is not set
+ # CONFIG_INET_ESP is not set
+ # CONFIG_INET_IPCOMP is not set
+ # CONFIG_INET_TUNNEL is not set
+ CONFIG_IP_TCPDIAG=y
+ # CONFIG_IP_TCPDIAG_IPV6 is not set
+ #
+ # IP: Virtual Server Configuration
+ #
+ # CONFIG_IP_VS is not set
+ # CONFIG_IPV6 is not set
+ CONFIG_NETFILTER=y
+ # CONFIG_NETFILTER_DEBUG is not set
+ CONFIG_BRIDGE_NETFILTER=y
+ #
+ # IP: Netfilter Configuration
+ #
+ CONFIG_IP_NF_CONNTRACK=m
+ CONFIG_IP_NF_CT_ACCT=y
+ # CONFIG_IP_NF_CONNTRACK_MARK is not set
+ # CONFIG_IP_NF_CT_PROTO_SCTP is not set
+ CONFIG_IP_NF_FTP=m
+ # CONFIG_IP_NF_IRC is not set
+ # CONFIG_IP_NF_TFTP is not set
+ # CONFIG_IP_NF_AMANDA is not set
+ # CONFIG_IP_NF_QUEUE is not set
+ CONFIG_IP_NF_IPTABLES=m
+ # CONFIG_IP_NF_MATCH_LIMIT is not set
+ # CONFIG_IP_NF_MATCH_IPRANGE is not set
+ # CONFIG_IP_NF_MATCH_MAC is not set
+ # CONFIG_IP_NF_MATCH_PKTTYPE is not set
+ # CONFIG_IP_NF_MATCH_MARK is not set
+ # CONFIG_IP_NF_MATCH_MULTIPORT is not set
+ # CONFIG_IP_NF_MATCH_TOS is not set
+ # CONFIG_IP_NF_MATCH_RECENT is not set
+ # CONFIG_IP_NF_MATCH_ECN is not set
+ # CONFIG_IP_NF_MATCH_DSCP is not set
+ # CONFIG_IP_NF_MATCH_AH_ESP is not set
+ # CONFIG_IP_NF_MATCH_LENGTH is not set
+ # CONFIG_IP_NF_MATCH_TTL is not set
+ # CONFIG_IP_NF_MATCH_TCPMSS is not set
+ # CONFIG_IP_NF_MATCH_HELPER is not set
+ # CONFIG_IP_NF_MATCH_STATE is not set
+ # CONFIG_IP_NF_MATCH_CONNTRACK is not set
+ # CONFIG_IP_NF_MATCH_OWNER is not set
+ # CONFIG_IP_NF_MATCH_PHYSDEV is not set
+ # CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+ # CONFIG_IP_NF_MATCH_REALM is not set
+ # CONFIG_IP_NF_MATCH_SCTP is not set
+ # CONFIG_IP_NF_MATCH_COMMENT is not set
+ # CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+ # CONFIG_IP_NF_FILTER is not set
+ # CONFIG_IP_NF_TARGET_LOG is not set
+ # CONFIG_IP_NF_TARGET_ULOG is not set
+ # CONFIG_IP_NF_TARGET_TCPMSS is not set
+ # CONFIG_IP_NF_NAT is not set
+ # CONFIG_IP_NF_MANGLE is not set
+ # CONFIG_IP_NF_RAW is not set
+ # CONFIG_IP_NF_ARPTABLES is not set
+ # CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+ # CONFIG_IP_NF_COMPAT_IPFWADM is not set
+ #
+ # Bridge: Netfilter Configuration
+ #
+ # CONFIG_BRIDGE_NF_EBTABLES is not set
+ #
+ # SCTP Configuration (EXPERIMENTAL)
+ #
+ # CONFIG_IP_SCTP is not set
+ # CONFIG_ATM is not set
+ CONFIG_BRIDGE=y
+ # CONFIG_VLAN_8021Q is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_LLC2 is not set
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+ # CONFIG_NET_DIVERT is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+ #
+ # QoS and/or fair queueing
+ #
+ # CONFIG_NET_SCHED is not set
+ # CONFIG_NET_CLS_ROUTE is not set
+ #
+ # Network testing
+ #
+ # CONFIG_NET_PKTGEN is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
+ CONFIG_NETDEVICES=y
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+ #
+ # ARCnet devices
+ #
+ # CONFIG_ARCNET is not set
+ #
+ # Ethernet (10 or 100Mbit)
+ #
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
+ # CONFIG_HAPPYMEAL is not set
+ # CONFIG_SUNGEM is not set
+ CONFIG_NET_VENDOR_3COM=y
+ # CONFIG_EL1 is not set
+ # CONFIG_EL2 is not set
+ # CONFIG_ELPLUS is not set
+ # CONFIG_EL16 is not set
+ # CONFIG_EL3 is not set
+ # CONFIG_3C515 is not set
+ CONFIG_VORTEX=y
+ # CONFIG_TYPHOON is not set
+ # CONFIG_LANCE is not set
+ # CONFIG_NET_VENDOR_SMC is not set
+ # CONFIG_NET_VENDOR_RACAL is not set
+ #
+ # Tulip family network device support
+ #
+ CONFIG_NET_TULIP=y
+ # CONFIG_DE2104X is not set
+ CONFIG_TULIP=y
+ # CONFIG_TULIP_MWI is not set
+ # CONFIG_TULIP_MMIO is not set
+ # CONFIG_TULIP_NAPI is not set
+ # CONFIG_DE4X5 is not set
+ # CONFIG_WINBOND_840 is not set
+ # CONFIG_DM9102 is not set
+ # CONFIG_AT1700 is not set
+ # CONFIG_DEPCA is not set
+ # CONFIG_HP100 is not set
+ # CONFIG_NET_ISA is not set
+ CONFIG_NET_PCI=y
+ CONFIG_PCNET32=y
+ # CONFIG_AMD8111_ETH is not set
+ # CONFIG_ADAPTEC_STARFIRE is not set
+ # CONFIG_AC3200 is not set
+ # CONFIG_APRICOT is not set
+ # CONFIG_B44 is not set
+ # CONFIG_FORCEDETH is not set
+ # CONFIG_CS89x0 is not set
+ # CONFIG_DGRS is not set
+ # CONFIG_EEPRO100 is not set
+ CONFIG_E100=y
+ # CONFIG_E100_NAPI is not set
+ # CONFIG_FEALNX is not set
+ # CONFIG_NATSEMI is not set
+ # CONFIG_NE2K_PCI is not set
+ # CONFIG_8139CP is not set
+ CONFIG_8139TOO=y
+ CONFIG_8139TOO_PIO=y
+ # CONFIG_8139TOO_TUNE_TWISTER is not set
+ # CONFIG_8139TOO_8129 is not set
+ # CONFIG_8139_OLD_RX_RESET is not set
+ # CONFIG_SIS900 is not set
+ # CONFIG_EPIC100 is not set
+ # CONFIG_SUNDANCE is not set
+ # CONFIG_TLAN is not set
+ CONFIG_VIA_RHINE=y
+ # CONFIG_VIA_RHINE_MMIO is not set
+ # CONFIG_NET_POCKET is not set
+ #
+ # Ethernet (1000 Mbit)
+ #
+ CONFIG_ACENIC=y
+ # CONFIG_ACENIC_OMIT_TIGON_I is not set
+ # CONFIG_DL2K is not set
+ CONFIG_E1000=y
+ # CONFIG_E1000_NAPI is not set
+ # CONFIG_NS83820 is not set
+ # CONFIG_HAMACHI is not set
+ # CONFIG_YELLOWFIN is not set
+ # CONFIG_R8169 is not set
+ # CONFIG_SK98LIN is not set
+ # CONFIG_VIA_VELOCITY is not set
+ CONFIG_TIGON3=y
+ #
+ # Ethernet (10000 Mbit)
+ #
+ # CONFIG_IXGB is not set
+ # CONFIG_S2IO is not set
+ #
+ # Token Ring devices
+ #
+ # CONFIG_TR is not set
+ #
+ # Wireless LAN (non-hamradio)
+ #
+ # CONFIG_NET_RADIO is not set
+ #
+ # Wan interfaces
+ #
+ # CONFIG_WAN is not set
+ # CONFIG_FDDI is not set
+ # CONFIG_HIPPI is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+ # CONFIG_NET_FC is not set
+ # CONFIG_SHAPER is not set
+ # CONFIG_NETCONSOLE is not set
+ #
+ # ISDN subsystem
+ #
+ # CONFIG_ISDN is not set
+ #
+ # Telephony Support
+ #
+ # CONFIG_PHONE is not set
+ #
+ # Input device support
+ #
+ CONFIG_INPUT=y
+ #
+ # Userland interfaces
+ #
+ CONFIG_INPUT_MOUSEDEV=y
+ CONFIG_INPUT_MOUSEDEV_PSAUX=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+ # CONFIG_INPUT_TSDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_EVBUG is not set
+ #
+ # Input I/O drivers
+ #
+ # CONFIG_GAMEPORT is not set
+ CONFIG_SOUND_GAMEPORT=y
+ CONFIG_SERIO=y
+ CONFIG_SERIO_I8042=y
+ CONFIG_SERIO_SERPORT=y
+ # CONFIG_SERIO_CT82C710 is not set
+ # CONFIG_SERIO_PCIPS2 is not set
+ # CONFIG_SERIO_RAW is not set
+ #
+ # Input Device Drivers
+ #
+ CONFIG_INPUT_KEYBOARD=y
+ CONFIG_KEYBOARD_ATKBD=y
+ # CONFIG_KEYBOARD_SUNKBD is not set
+ # CONFIG_KEYBOARD_LKKBD is not set
+ # CONFIG_KEYBOARD_XTKBD is not set
+ # CONFIG_KEYBOARD_NEWTON is not set
+ CONFIG_INPUT_MOUSE=y
+ CONFIG_MOUSE_PS2=y
+ # CONFIG_MOUSE_SERIAL is not set
+ # CONFIG_MOUSE_INPORT is not set
+ # CONFIG_MOUSE_LOGIBM is not set
+ # CONFIG_MOUSE_PC110PAD is not set
+ # CONFIG_MOUSE_VSXXXAA is not set
+ # CONFIG_INPUT_JOYSTICK is not set
+ # CONFIG_INPUT_TOUCHSCREEN is not set
+ # CONFIG_INPUT_MISC is not set
+ #
+ # Character devices
+ #
+ CONFIG_VT=y
+ CONFIG_VT_CONSOLE=y
+ CONFIG_HW_CONSOLE=y
+ # CONFIG_SERIAL_NONSTANDARD is not set
+ #
+ # Serial drivers
+ #
+ # CONFIG_SERIAL_8250 is not set
+ #
+ # Non-8250 serial port support
+ #
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+ #
+ # IPMI
+ #
+ # CONFIG_IPMI_HANDLER is not set
+ #
+ # Watchdog Cards
+ #
+ # CONFIG_WATCHDOG is not set
+ # CONFIG_HW_RANDOM is not set
+ # CONFIG_NVRAM is not set
+ # CONFIG_RTC is not set
+ # CONFIG_GEN_RTC is not set
+ # CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_APPLICOM is not set
+ # CONFIG_SONYPI is not set
+ #
+ # Ftape, the floppy tape device driver
+ #
+ # CONFIG_FTAPE is not set
+ # CONFIG_AGP is not set
+ # CONFIG_DRM is not set
+ # CONFIG_MWAVE is not set
+ # CONFIG_RAW_DRIVER is not set
+ # CONFIG_HANGCHECK_TIMER is not set
+ #
+ # I2C support
+ #
+ # CONFIG_I2C is not set
+ #
+ # Dallas's 1-wire bus
+ #
+ # CONFIG_W1 is not set
+ #
+ # Misc devices
+ #
+ # CONFIG_IBM_ASM is not set
+ #
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
+ #
+ # Digital Video Broadcasting Devices
+ #
+ # CONFIG_DVB is not set
+ #
+ # Graphics support
+ #
+ # CONFIG_FB is not set
+ # CONFIG_VIDEO_SELECT is not set
+ #
+ # Console display driver support
+ #
+ CONFIG_VGA_CONSOLE=y
+ # CONFIG_MDA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+ #
+ # Sound
+ #
+ # CONFIG_SOUND is not set
+ #
+ # USB support
+ #
+ # CONFIG_USB is not set
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+ #
+ # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+ #
+ #
+ # USB Gadget Support
+ #
+ # CONFIG_USB_GADGET is not set
+ #
+ # File systems
+ #
+ CONFIG_EXT2_FS=y
+ # CONFIG_EXT2_FS_XATTR is not set
+ CONFIG_EXT3_FS=y
+ CONFIG_EXT3_FS_XATTR=y
+ # CONFIG_EXT3_FS_POSIX_ACL is not set
+ # CONFIG_EXT3_FS_SECURITY is not set
+ CONFIG_JBD=y
+ # CONFIG_JBD_DEBUG is not set
+ CONFIG_FS_MBCACHE=y
+ CONFIG_REISERFS_FS=y
+ # CONFIG_REISERFS_CHECK is not set
+ # CONFIG_REISERFS_PROC_INFO is not set
+ # CONFIG_REISERFS_FS_XATTR is not set
+ # CONFIG_JFS_FS is not set
+ # CONFIG_XFS_FS is not set
+ # CONFIG_MINIX_FS is not set
+ # CONFIG_ROMFS_FS is not set
+ # CONFIG_QUOTA is not set
+ CONFIG_DNOTIFY=y
+ # CONFIG_AUTOFS_FS is not set
+ # CONFIG_AUTOFS4_FS is not set
+ #
+ # CD-ROM/DVD Filesystems
+ #
+ CONFIG_ISO9660_FS=y
+ CONFIG_JOLIET=y
+ CONFIG_ZISOFS=y
+ CONFIG_ZISOFS_FS=y
+ # CONFIG_UDF_FS is not set
+ #
+ # DOS/FAT/NT Filesystems
+ #
+ CONFIG_FAT_FS=m
+ CONFIG_MSDOS_FS=m
+ CONFIG_VFAT_FS=m
+ CONFIG_FAT_DEFAULT_CODEPAGE=437
+ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ # CONFIG_NTFS_FS is not set
+ #
+ # Pseudo filesystems
+ #
+ CONFIG_PROC_FS=y
+ CONFIG_PROC_KCORE=y
+ CONFIG_SYSFS=y
+ # CONFIG_DEVFS_FS is not set
+ # CONFIG_DEVPTS_FS_XATTR is not set
+ CONFIG_TMPFS=y
+ # CONFIG_TMPFS_XATTR is not set
+ # CONFIG_HUGETLBFS is not set
+ # CONFIG_HUGETLB_PAGE is not set
+ CONFIG_RAMFS=y
+ #
+ # Miscellaneous filesystems
+ #
+ # CONFIG_ADFS_FS is not set
+ # CONFIG_AFFS_FS is not set
+ # CONFIG_HFS_FS is not set
+ # CONFIG_HFSPLUS_FS is not set
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
+ # CONFIG_CRAMFS is not set
+ # CONFIG_VXFS_FS is not set
+ # CONFIG_HPFS_FS is not set
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+ #
+ # Network File Systems
+ #
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V4 is not set
+ # CONFIG_NFS_DIRECTIO is not set
+ CONFIG_NFSD=m
+ CONFIG_NFSD_V3=y
+ # CONFIG_NFSD_V4 is not set
+ CONFIG_NFSD_TCP=y
+ CONFIG_ROOT_NFS=y
+ CONFIG_LOCKD=y
+ CONFIG_LOCKD_V4=y
+ CONFIG_EXPORTFS=m
+ CONFIG_SUNRPC=y
+ # CONFIG_RPCSEC_GSS_KRB5 is not set
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+ # CONFIG_CIFS is not set
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+ #
+ # Native Language Support
+ #
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
+ # CONFIG_NLS_CODEPAGE_737 is not set
+ # CONFIG_NLS_CODEPAGE_775 is not set
+ # CONFIG_NLS_CODEPAGE_850 is not set
+ # CONFIG_NLS_CODEPAGE_852 is not set
+ # CONFIG_NLS_CODEPAGE_855 is not set
+ # CONFIG_NLS_CODEPAGE_857 is not set
+ # CONFIG_NLS_CODEPAGE_860 is not set
+ # CONFIG_NLS_CODEPAGE_861 is not set
+ # CONFIG_NLS_CODEPAGE_862 is not set
+ # CONFIG_NLS_CODEPAGE_863 is not set
+ # CONFIG_NLS_CODEPAGE_864 is not set
+ # CONFIG_NLS_CODEPAGE_865 is not set
+ # CONFIG_NLS_CODEPAGE_866 is not set
+ # CONFIG_NLS_CODEPAGE_869 is not set
+ # CONFIG_NLS_CODEPAGE_936 is not set
+ # CONFIG_NLS_CODEPAGE_950 is not set
+ # CONFIG_NLS_CODEPAGE_932 is not set
+ # CONFIG_NLS_CODEPAGE_949 is not set
+ # CONFIG_NLS_CODEPAGE_874 is not set
+ # CONFIG_NLS_ISO8859_8 is not set
+ # CONFIG_NLS_CODEPAGE_1250 is not set
+ # CONFIG_NLS_CODEPAGE_1251 is not set
+ # CONFIG_NLS_ASCII is not set
+ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_NLS_ISO8859_2 is not set
+ # CONFIG_NLS_ISO8859_3 is not set
+ # CONFIG_NLS_ISO8859_4 is not set
+ # CONFIG_NLS_ISO8859_5 is not set
+ # CONFIG_NLS_ISO8859_6 is not set
+ # CONFIG_NLS_ISO8859_7 is not set
+ # CONFIG_NLS_ISO8859_9 is not set
+ # CONFIG_NLS_ISO8859_13 is not set
+ # CONFIG_NLS_ISO8859_14 is not set
+ # CONFIG_NLS_ISO8859_15 is not set
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+ #
+ # Security options
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+ #
+ # Cryptographic options
+ #
+ CONFIG_CRYPTO=y
+ CONFIG_CRYPTO_HMAC=y
+ # CONFIG_CRYPTO_NULL is not set
+ # CONFIG_CRYPTO_MD4 is not set
+ CONFIG_CRYPTO_MD5=m
+ CONFIG_CRYPTO_SHA1=m
+ # CONFIG_CRYPTO_SHA256 is not set
+ # CONFIG_CRYPTO_SHA512 is not set
+ # CONFIG_CRYPTO_WP512 is not set
+ CONFIG_CRYPTO_DES=m
+ # CONFIG_CRYPTO_BLOWFISH is not set
+ # CONFIG_CRYPTO_TWOFISH is not set
+ # CONFIG_CRYPTO_SERPENT is not set
+ # CONFIG_CRYPTO_AES_586 is not set
+ # CONFIG_CRYPTO_CAST5 is not set
+ # CONFIG_CRYPTO_CAST6 is not set
+ # CONFIG_CRYPTO_TEA is not set
+ # CONFIG_CRYPTO_ARC4 is not set
+ # CONFIG_CRYPTO_KHAZAD is not set
+ # CONFIG_CRYPTO_ANUBIS is not set
+ # CONFIG_CRYPTO_DEFLATE is not set
+ # CONFIG_CRYPTO_MICHAEL_MIC is not set
+ CONFIG_CRYPTO_CRC32C=m
+ # CONFIG_CRYPTO_TEST is not set
+ #
+ # Library routines
+ #
+ # CONFIG_CRC_CCITT is not set
+ CONFIG_CRC32=y
+ CONFIG_LIBCRC32C=y
+ CONFIG_ZLIB_INFLATE=y
index 0000000000000000000000000000000000000000,e90dd4bc5a21160e7d97f4d78efb74070fdf8728..56dcbfd336a7b740b5d0d14dbfd0fe40ad7677ab
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,519 +1,521 @@@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.10-rc3-xenU
+ # Sun Dec 26 10:35:15 2004
+ #
+ CONFIG_XEN=y
+ CONFIG_ARCH_XEN=y
+ CONFIG_NO_IDLE_HZ=y
+ #
+ # XEN
+ #
+ # CONFIG_XEN_PRIVILEGED_GUEST is not set
+ # CONFIG_XEN_PHYSDEV_ACCESS is not set
+ # CONFIG_XEN_BLKDEV_BACKEND is not set
++# CONFIG_XEN_BLKDEV_TAP_BE is not set
+ # CONFIG_XEN_NETDEV_BACKEND is not set
+ CONFIG_XEN_BLKDEV_FRONTEND=y
+ CONFIG_XEN_NETDEV_FRONTEND=y
++# CONFIG_XEN_BLKDEV_TAP is not set
+ # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
+ CONFIG_XEN_WRITABLE_PAGETABLES=y
+ CONFIG_XEN_SCRUB_PAGES=y
+ CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+ CONFIG_X86=y
+ # CONFIG_X86_64 is not set
+ #
+ # Code maturity level options
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_LOCK_KERNEL=y
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ CONFIG_SYSCTL=y
+ # CONFIG_AUDIT is not set
+ CONFIG_LOG_BUF_SHIFT=14
+ CONFIG_HOTPLUG=y
+ CONFIG_KOBJECT_UEVENT=y
+ # CONFIG_IKCONFIG is not set
+ # CONFIG_EMBEDDED is not set
+ CONFIG_KALLSYMS=y
+ # CONFIG_KALLSYMS_ALL is not set
+ # CONFIG_KALLSYMS_EXTRA_PASS is not set
+ CONFIG_FUTEX=y
+ CONFIG_EPOLL=y
+ # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+ CONFIG_SHMEM=y
+ CONFIG_CC_ALIGN_FUNCTIONS=0
+ CONFIG_CC_ALIGN_LABELS=0
+ CONFIG_CC_ALIGN_LOOPS=0
+ CONFIG_CC_ALIGN_JUMPS=0
+ # CONFIG_TINY_SHMEM is not set
+ #
+ # Loadable module support
+ #
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+ CONFIG_OBSOLETE_MODPARM=y
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+ #
+ # X86 Processor Configuration
+ #
+ CONFIG_XENARCH="i386"
+ CONFIG_MMU=y
+ CONFIG_UID16=y
+ CONFIG_GENERIC_ISA_DMA=y
+ CONFIG_GENERIC_IOMAP=y
+ # CONFIG_M386 is not set
+ # CONFIG_M486 is not set
+ # CONFIG_M586 is not set
+ # CONFIG_M586TSC is not set
+ # CONFIG_M586MMX is not set
+ # CONFIG_M686 is not set
+ # CONFIG_MPENTIUMII is not set
+ # CONFIG_MPENTIUMIII is not set
+ # CONFIG_MPENTIUMM is not set
+ CONFIG_MPENTIUM4=y
+ # CONFIG_MK6 is not set
+ # CONFIG_MK7 is not set
+ # CONFIG_MK8 is not set
+ # CONFIG_MCRUSOE is not set
+ # CONFIG_MEFFICEON is not set
+ # CONFIG_MWINCHIPC6 is not set
+ # CONFIG_MWINCHIP2 is not set
+ # CONFIG_MWINCHIP3D is not set
+ # CONFIG_MCYRIXIII is not set
+ # CONFIG_MVIAC3_2 is not set
+ # CONFIG_X86_GENERIC is not set
+ CONFIG_X86_CMPXCHG=y
+ CONFIG_X86_XADD=y
+ CONFIG_X86_L1_CACHE_SHIFT=7
+ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+ CONFIG_X86_WP_WORKS_OK=y
+ CONFIG_X86_INVLPG=y
+ CONFIG_X86_BSWAP=y
+ CONFIG_X86_POPAD_OK=y
+ CONFIG_X86_GOOD_APIC=y
+ CONFIG_X86_INTEL_USERCOPY=y
+ CONFIG_X86_USE_PPRO_CHECKSUM=y
+ # CONFIG_HPET_TIMER is not set
+ # CONFIG_HPET_EMULATE_RTC is not set
+ # CONFIG_SMP is not set
+ CONFIG_PREEMPT=y
+ CONFIG_X86_CPUID=y
+ #
+ # Firmware Drivers
+ #
+ # CONFIG_EDD is not set
+ CONFIG_NOHIGHMEM=y
+ # CONFIG_HIGHMEM4G is not set
+ CONFIG_HAVE_DEC_LOCK=y
+ # CONFIG_REGPARM is not set
+ #
+ # Kernel hacking
+ #
+ CONFIG_DEBUG_KERNEL=y
+ CONFIG_EARLY_PRINTK=y
+ # CONFIG_DEBUG_STACKOVERFLOW is not set
+ # CONFIG_DEBUG_STACK_USAGE is not set
+ CONFIG_DEBUG_SLAB=y
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ CONFIG_DEBUG_PAGEALLOC=y
+ # CONFIG_DEBUG_INFO is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_FRAME_POINTER is not set
+ # CONFIG_4KSTACKS is not set
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_X86_BIOS_REBOOT=y
+ CONFIG_PC=y
+ #
+ # Executable file formats
+ #
+ CONFIG_BINFMT_ELF=y
+ # CONFIG_BINFMT_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+ #
+ # Device Drivers
+ #
+ #
+ # Generic Driver Options
+ #
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_DEBUG_DRIVER is not set
+ #
+ # Block devices
+ #
+ # CONFIG_BLK_DEV_FD is not set
+ CONFIG_BLK_DEV_LOOP=m
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+ CONFIG_BLK_DEV_NBD=m
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=4096
+ CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ # CONFIG_LBD is not set
+ # CONFIG_CDROM_PKTCDVD is not set
+ #
+ # IO Schedulers
+ #
+ CONFIG_IOSCHED_NOOP=y
+ CONFIG_IOSCHED_AS=y
+ CONFIG_IOSCHED_DEADLINE=y
+ CONFIG_IOSCHED_CFQ=y
+ #
+ # SCSI device support
+ #
+ CONFIG_SCSI=m
+ CONFIG_SCSI_PROC_FS=y
+ #
+ # SCSI support type (disk, tape, CD-ROM)
+ #
+ CONFIG_BLK_DEV_SD=m
+ # CONFIG_CHR_DEV_ST is not set
+ # CONFIG_CHR_DEV_OSST is not set
+ # CONFIG_BLK_DEV_SR is not set
+ # CONFIG_CHR_DEV_SG is not set
+ #
+ # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+ #
+ # CONFIG_SCSI_MULTI_LUN is not set
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+ #
+ # SCSI Transport Attributes
+ #
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ #
+ # SCSI low-level drivers
+ #
+ # CONFIG_SCSI_SATA is not set
+ # CONFIG_SCSI_DEBUG is not set
+ #
+ # Multi-device support (RAID and LVM)
+ #
+ # CONFIG_MD is not set
+ #
+ # Networking support
+ #
+ CONFIG_NET=y
+ #
+ # Networking options
+ #
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ # CONFIG_NETLINK_DEV is not set
+ CONFIG_UNIX=y
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+ # CONFIG_IP_ADVANCED_ROUTER is not set
+ CONFIG_IP_PNP=y
+ # CONFIG_IP_PNP_DHCP is not set
+ # CONFIG_IP_PNP_BOOTP is not set
+ # CONFIG_IP_PNP_RARP is not set
+ # CONFIG_NET_IPIP is not set
+ # CONFIG_NET_IPGRE is not set
+ # CONFIG_ARPD is not set
+ # CONFIG_SYN_COOKIES is not set
+ # CONFIG_INET_AH is not set
+ # CONFIG_INET_ESP is not set
+ # CONFIG_INET_IPCOMP is not set
+ # CONFIG_INET_TUNNEL is not set
+ CONFIG_IP_TCPDIAG=y
+ # CONFIG_IP_TCPDIAG_IPV6 is not set
+ # CONFIG_IPV6 is not set
+ # CONFIG_NETFILTER is not set
+ #
+ # SCTP Configuration (EXPERIMENTAL)
+ #
+ # CONFIG_IP_SCTP is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_VLAN_8021Q is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_LLC2 is not set
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+ # CONFIG_NET_DIVERT is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+ #
+ # QoS and/or fair queueing
+ #
+ # CONFIG_NET_SCHED is not set
+ # CONFIG_NET_CLS_ROUTE is not set
+ #
+ # Network testing
+ #
+ # CONFIG_NET_PKTGEN is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
+ CONFIG_NETDEVICES=y
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+ #
+ # Ethernet (10 or 100Mbit)
+ #
+ # CONFIG_NET_ETHERNET is not set
+ #
+ # Ethernet (1000 Mbit)
+ #
+ #
+ # Ethernet (10000 Mbit)
+ #
+ #
+ # Token Ring devices
+ #
+ #
+ # Wireless LAN (non-hamradio)
+ #
+ # CONFIG_NET_RADIO is not set
+ #
+ # Wan interfaces
+ #
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+ # CONFIG_SHAPER is not set
+ # CONFIG_NETCONSOLE is not set
+ CONFIG_UNIX98_PTYS=y
+ #
+ # File systems
+ #
+ CONFIG_EXT2_FS=y
+ # CONFIG_EXT2_FS_XATTR is not set
+ CONFIG_EXT3_FS=y
+ CONFIG_EXT3_FS_XATTR=y
+ # CONFIG_EXT3_FS_POSIX_ACL is not set
+ # CONFIG_EXT3_FS_SECURITY is not set
+ CONFIG_JBD=y
+ # CONFIG_JBD_DEBUG is not set
+ CONFIG_FS_MBCACHE=y
+ CONFIG_REISERFS_FS=y
+ # CONFIG_REISERFS_CHECK is not set
+ # CONFIG_REISERFS_PROC_INFO is not set
+ # CONFIG_REISERFS_FS_XATTR is not set
+ # CONFIG_JFS_FS is not set
+ # CONFIG_XFS_FS is not set
+ # CONFIG_MINIX_FS is not set
+ # CONFIG_ROMFS_FS is not set
+ # CONFIG_QUOTA is not set
+ CONFIG_DNOTIFY=y
+ CONFIG_AUTOFS_FS=y
+ CONFIG_AUTOFS4_FS=y
+ #
+ # CD-ROM/DVD Filesystems
+ #
+ CONFIG_ISO9660_FS=y
+ CONFIG_JOLIET=y
+ CONFIG_ZISOFS=y
+ CONFIG_ZISOFS_FS=y
+ # CONFIG_UDF_FS is not set
+ #
+ # DOS/FAT/NT Filesystems
+ #
+ CONFIG_FAT_FS=m
+ CONFIG_MSDOS_FS=m
+ CONFIG_VFAT_FS=m
+ CONFIG_FAT_DEFAULT_CODEPAGE=437
+ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ # CONFIG_NTFS_FS is not set
+ #
+ # Pseudo filesystems
+ #
+ CONFIG_PROC_FS=y
+ CONFIG_PROC_KCORE=y
+ CONFIG_SYSFS=y
+ # CONFIG_DEVFS_FS is not set
+ CONFIG_DEVPTS_FS_XATTR=y
+ # CONFIG_DEVPTS_FS_SECURITY is not set
+ CONFIG_TMPFS=y
+ # CONFIG_TMPFS_XATTR is not set
+ # CONFIG_HUGETLBFS is not set
+ # CONFIG_HUGETLB_PAGE is not set
+ CONFIG_RAMFS=y
+ #
+ # Miscellaneous filesystems
+ #
+ # CONFIG_ADFS_FS is not set
+ # CONFIG_AFFS_FS is not set
+ # CONFIG_HFS_FS is not set
+ # CONFIG_HFSPLUS_FS is not set
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
+ # CONFIG_CRAMFS is not set
+ # CONFIG_VXFS_FS is not set
+ # CONFIG_HPFS_FS is not set
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+ #
+ # Network File Systems
+ #
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V4 is not set
+ # CONFIG_NFS_DIRECTIO is not set
+ # CONFIG_NFSD is not set
+ CONFIG_ROOT_NFS=y
+ CONFIG_LOCKD=y
+ CONFIG_LOCKD_V4=y
+ # CONFIG_EXPORTFS is not set
+ CONFIG_SUNRPC=y
+ # CONFIG_RPCSEC_GSS_KRB5 is not set
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+ # CONFIG_CIFS is not set
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+ #
+ # Native Language Support
+ #
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
+ # CONFIG_NLS_CODEPAGE_737 is not set
+ # CONFIG_NLS_CODEPAGE_775 is not set
+ # CONFIG_NLS_CODEPAGE_850 is not set
+ # CONFIG_NLS_CODEPAGE_852 is not set
+ # CONFIG_NLS_CODEPAGE_855 is not set
+ # CONFIG_NLS_CODEPAGE_857 is not set
+ # CONFIG_NLS_CODEPAGE_860 is not set
+ # CONFIG_NLS_CODEPAGE_861 is not set
+ # CONFIG_NLS_CODEPAGE_862 is not set
+ # CONFIG_NLS_CODEPAGE_863 is not set
+ # CONFIG_NLS_CODEPAGE_864 is not set
+ # CONFIG_NLS_CODEPAGE_865 is not set
+ # CONFIG_NLS_CODEPAGE_866 is not set
+ # CONFIG_NLS_CODEPAGE_869 is not set
+ # CONFIG_NLS_CODEPAGE_936 is not set
+ # CONFIG_NLS_CODEPAGE_950 is not set
+ # CONFIG_NLS_CODEPAGE_932 is not set
+ # CONFIG_NLS_CODEPAGE_949 is not set
+ # CONFIG_NLS_CODEPAGE_874 is not set
+ # CONFIG_NLS_ISO8859_8 is not set
+ # CONFIG_NLS_CODEPAGE_1250 is not set
+ # CONFIG_NLS_CODEPAGE_1251 is not set
+ # CONFIG_NLS_ASCII is not set
+ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_NLS_ISO8859_2 is not set
+ # CONFIG_NLS_ISO8859_3 is not set
+ # CONFIG_NLS_ISO8859_4 is not set
+ # CONFIG_NLS_ISO8859_5 is not set
+ # CONFIG_NLS_ISO8859_6 is not set
+ # CONFIG_NLS_ISO8859_7 is not set
+ # CONFIG_NLS_ISO8859_9 is not set
+ # CONFIG_NLS_ISO8859_13 is not set
+ # CONFIG_NLS_ISO8859_14 is not set
+ # CONFIG_NLS_ISO8859_15 is not set
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+ #
+ # Security options
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+ #
+ # Cryptographic options
+ #
+ CONFIG_CRYPTO=y
+ # CONFIG_CRYPTO_HMAC is not set
+ # CONFIG_CRYPTO_NULL is not set
+ # CONFIG_CRYPTO_MD4 is not set
+ CONFIG_CRYPTO_MD5=m
+ # CONFIG_CRYPTO_SHA1 is not set
+ # CONFIG_CRYPTO_SHA256 is not set
+ # CONFIG_CRYPTO_SHA512 is not set
+ # CONFIG_CRYPTO_WP512 is not set
+ # CONFIG_CRYPTO_DES is not set
+ # CONFIG_CRYPTO_BLOWFISH is not set
+ # CONFIG_CRYPTO_TWOFISH is not set
+ # CONFIG_CRYPTO_SERPENT is not set
+ # CONFIG_CRYPTO_AES_586 is not set
+ # CONFIG_CRYPTO_CAST5 is not set
+ # CONFIG_CRYPTO_CAST6 is not set
+ # CONFIG_CRYPTO_TEA is not set
+ # CONFIG_CRYPTO_ARC4 is not set
+ # CONFIG_CRYPTO_KHAZAD is not set
+ # CONFIG_CRYPTO_ANUBIS is not set
+ # CONFIG_CRYPTO_DEFLATE is not set
+ # CONFIG_CRYPTO_MICHAEL_MIC is not set
+ CONFIG_CRYPTO_CRC32C=m
+ # CONFIG_CRYPTO_TEST is not set
+ #
+ # Library routines
+ #
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC32 is not set
+ CONFIG_LIBCRC32C=m
+ CONFIG_ZLIB_INFLATE=y
index 0000000000000000000000000000000000000000,30609afa6608a727e5de63f059d87db42fb64a83..e29487ea1ea11bd980ce525d7e5c66697b995414
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,956 +1,953 @@@
 -      bool
 -      default n
 -#config SMP
 -#     bool "Symmetric multi-processing support"
 -#     ---help---
 -#       This enables support for systems with more than one CPU. If you have
 -#       a system with only one CPU, like most personal computers, say N. If
 -#       you have a system with more than one CPU, say Y.
 -#
 -#       If you say N here, the kernel will run on single and multiprocessor
 -#       machines, but will use only one CPU of a multiprocessor machine. If
 -#       you say Y here, the kernel will run on many, but not all,
 -#       singleprocessor machines. On a singleprocessor machine, the kernel
 -#       will run faster if you say N here.
 -#
 -#       Note that if you say Y here and choose architecture "586" or
 -#       "Pentium" under "Processor family", the kernel will not work on 486
 -#       architectures. Similarly, multiprocessor kernels for the "PPro"
 -#       architecture may not work on all Pentium based boards.
 -#
 -#       People using multiprocessor machines who say Y here should also say
 -#       Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
 -#       Management" code will be disabled if you say Y here.
 -#
 -#       See also the <file:Documentation/smp.txt>,
 -#       <file:Documentation/i386/IO-APIC.txt>,
 -#       <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
 -#       <http://www.tldp.org/docs.html#howto>.
 -#
 -#       If you don't know what to do here, say N.
+ #
+ # For a description of the syntax of this configuration file,
+ # see Documentation/kbuild/kconfig-language.txt.
+ #
+ menu "X86 Processor Configuration"
+ config XENARCH
+       string
+       default i386
+ config MMU
+       bool
+       default y
+ config SBUS
+       bool
+ config UID16
+       bool
+       default y
+ config GENERIC_ISA_DMA
+       bool
+       default y
+ config GENERIC_IOMAP
+       bool
+       default y
+ choice
+       prompt "Processor family"
+       default M686
+ config M386
+       bool "386"
+       ---help---
+         This is the processor type of your CPU. This information is used for
+         optimizing purposes. In order to compile a kernel that can run on
+         all x86 CPU types (albeit not optimally fast), you can specify
+         "386" here.
+         The kernel will not necessarily run on earlier architectures than
+         the one you have chosen, e.g. a Pentium optimized kernel will run on
+         a PPro, but not necessarily on a i486.
+         Here are the settings recommended for greatest speed:
+         - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI
+         486DLC/DLC2, UMC 486SX-S and NexGen Nx586.  Only "386" kernels
+         will run on a 386 class machine.
+         - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or
+         SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S.
+         - "586" for generic Pentium CPUs lacking the TSC
+         (time stamp counter) register.
+         - "Pentium-Classic" for the Intel Pentium.
+         - "Pentium-MMX" for the Intel Pentium MMX.
+         - "Pentium-Pro" for the Intel Pentium Pro.
+         - "Pentium-II" for the Intel Pentium II or pre-Coppermine Celeron.
+         - "Pentium-III" for the Intel Pentium III or Coppermine Celeron.
+         - "Pentium-4" for the Intel Pentium 4 or P4-based Celeron.
+         - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D).
+         - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird).
+         - "Crusoe" for the Transmeta Crusoe series.
+         - "Efficeon" for the Transmeta Efficeon series.
+         - "Winchip-C6" for original IDT Winchip.
+         - "Winchip-2" for IDT Winchip 2.
+         - "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
+         - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
+         - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
+         If you don't know what to do, choose "386".
+ config M486
+       bool "486"
+       help
+         Select this for a 486 series processor, either Intel or one of the
+         compatible processors from AMD, Cyrix, IBM, or Intel.  Includes DX,
+         DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or
+         U5S.
+ config M586
+       bool "586/K5/5x86/6x86/6x86MX"
+       help
+         Select this for an 586 or 686 series processor such as the AMD K5,
+         the Cyrix 5x86, 6x86 and 6x86MX.  This choice does not
+         assume the RDTSC (Read Time Stamp Counter) instruction.
+ config M586TSC
+       bool "Pentium-Classic"
+       help
+         Select this for a Pentium Classic processor with the RDTSC (Read
+         Time Stamp Counter) instruction for benchmarking.
+ config M586MMX
+       bool "Pentium-MMX"
+       help
+         Select this for a Pentium with the MMX graphics/multimedia
+         extended instructions.
+ config M686
+       bool "Pentium-Pro"
+       help
+         Select this for Intel Pentium Pro chips.  This enables the use of
+         Pentium Pro extended instructions, and disables the init-time guard
+         against the f00f bug found in earlier Pentiums.
+ config MPENTIUMII
+       bool "Pentium-II/Celeron(pre-Coppermine)"
+       help
+         Select this for Intel chips based on the Pentium-II and
+         pre-Coppermine Celeron core.  This option enables an unaligned
+         copy optimization, compiles the kernel with optimization flags
+         tailored for the chip, and applies any applicable Pentium Pro
+         optimizations.
+ config MPENTIUMIII
+       bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon"
+       help
+         Select this for Intel chips based on the Pentium-III and
+         Celeron-Coppermine core.  This option enables use of some
+         extended prefetch instructions in addition to the Pentium II
+         extensions.
+ config MPENTIUMM
+       bool "Pentium M"
+       help
+         Select this for Intel Pentium M (not Pentium-4 M)
+         notebook chips.
+ config MPENTIUM4
+       bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon"
+       help
+         Select this for Intel Pentium 4 chips.  This includes the
+         Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M
+         (not Pentium M) chips.  This option enables compile flags
+         optimized for the chip, uses the correct cache shift, and
+         applies any applicable Pentium III optimizations.
+ config MK6
+       bool "K6/K6-II/K6-III"
+       help
+         Select this for an AMD K6-family processor.  Enables use of
+         some extended instructions, and passes appropriate optimization
+         flags to GCC.
+ config MK7
+       bool "Athlon/Duron/K7"
+       help
+         Select this for an AMD Athlon K7-family processor.  Enables use of
+         some extended instructions, and passes appropriate optimization
+         flags to GCC.
+ config MK8
+       bool "Opteron/Athlon64/Hammer/K8"
+       help
+         Select this for an AMD Opteron or Athlon64 Hammer-family processor.  Enables
+         use of some extended instructions, and passes appropriate optimization
+         flags to GCC.
+ config MCRUSOE
+       bool "Crusoe"
+       help
+         Select this for a Transmeta Crusoe processor.  Treats the processor
+         like a 586 with TSC, and sets some GCC optimization flags (like a
+         Pentium Pro with no alignment requirements).
+ config MEFFICEON
+       bool "Efficeon"
+       help
+         Select this for a Transmeta Efficeon processor.
+ config MWINCHIPC6
+       bool "Winchip-C6"
+       help
+         Select this for an IDT Winchip C6 chip.  Linux and GCC
+         treat this chip as a 586TSC with some extended instructions
+         and alignment requirements.
+ config MWINCHIP2
+       bool "Winchip-2"
+       help
+         Select this for an IDT Winchip-2.  Linux and GCC
+         treat this chip as a 586TSC with some extended instructions
+         and alignment requirements.
+ config MWINCHIP3D
+       bool "Winchip-2A/Winchip-3"
+       help
+         Select this for an IDT Winchip-2A or 3.  Linux and GCC
+         treat this chip as a 586TSC with some extended instructions
+         and alignment reqirements.  Also enable out of order memory
+         stores for this CPU, which can increase performance of some
+         operations.
+ config MCYRIXIII
+       bool "CyrixIII/VIA-C3"
+       help
+         Select this for a Cyrix III or C3 chip.  Presently Linux and GCC
+         treat this chip as a generic 586. Whilst the CPU is 686 class,
+         it lacks the cmov extension which gcc assumes is present when
+         generating 686 code.
+         Note that Nehemiah (Model 9) and above will not boot with this
+         kernel due to them lacking the 3DNow! instructions used in earlier
+         incarnations of the CPU.
+ config MVIAC3_2
+       bool "VIA C3-2 (Nehemiah)"
+       help
+         Select this for a VIA C3 "Nehemiah". Selecting this enables usage
+         of SSE and tells gcc to treat the CPU as a 686.
+         Note, this kernel will not boot on older (pre model 9) C3s.
+ endchoice
+ config X86_GENERIC
+        bool "Generic x86 support"
+        help
+         Instead of just including optimizations for the selected
+         x86 variant (e.g. PII, Crusoe or Athlon), include some more
+         generic optimizations as well. This will make the kernel
+         perform better on x86 CPUs other than that selected.
+         This is really intended for distributors who need more
+         generic optimizations.
+ #
+ # Define implied options from the CPU selection here
+ #
+ config X86_CMPXCHG
+       bool
+       depends on !M386
+       default y
+ config X86_XADD
+       bool
+       depends on !M386
+       default y
+ config X86_L1_CACHE_SHIFT
+       int
+       default "7" if MPENTIUM4 || X86_GENERIC
+       default "4" if X86_ELAN || M486 || M386
+       default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2
+       default "6" if MK7 || MK8 || MPENTIUMM
+ config RWSEM_GENERIC_SPINLOCK
+       bool
+       depends on M386
+       default y
+ config RWSEM_XCHGADD_ALGORITHM
+       bool
+       depends on !M386
+       default y
+ config X86_PPRO_FENCE
+       bool
+       depends on M686 || M586MMX || M586TSC || M586 || M486 || M386
+       default y
+ config X86_F00F_BUG
+       bool
+       depends on M586MMX || M586TSC || M586 || M486 || M386
+       default y
+ config X86_WP_WORKS_OK
+       bool
+       depends on !M386
+       default y
+ config X86_INVLPG
+       bool
+       depends on !M386
+       default y
+ config X86_BSWAP
+       bool
+       depends on !M386
+       default y
+ config X86_POPAD_OK
+       bool
+       depends on !M386
+       default y
+ config X86_ALIGNMENT_16
+       bool
+       depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2
+       default y
+ config X86_GOOD_APIC
+       bool
+       depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON
+       default y
+ config X86_INTEL_USERCOPY
+       bool
+       depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON
+       default y
+ config X86_USE_PPRO_CHECKSUM
+       bool
+       depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON
+       default y
+ config X86_USE_3DNOW
+       bool
+       depends on MCYRIXIII || MK7
+       default y
+ config X86_OOSTORE
+       bool
+       depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
+       default y
+ config HPET_TIMER
+       bool
+       default n
+ #config HPET_TIMER
+ #     bool "HPET Timer Support"
+ #     help
+ #       This enables the use of the HPET for the kernel's internal timer.
+ #       HPET is the next generation timer replacing legacy 8254s.
+ #       You can safely choose Y here.  However, HPET will only be
+ #       activated if the platform and the BIOS support this feature.
+ #       Otherwise the 8254 will be used for timing services.
+ #
+ #       Choose N to continue using the legacy 8254 timer.
+ config HPET_EMULATE_RTC
+       def_bool HPET_TIMER && RTC=y
+ config SMP
 -config X86_LOCAL_APIC
 -      bool
 -      depends on (X86_VISWS || SMP) && !X86_VOYAGER
 -      default y
 -
 -config X86_IO_APIC
 -      bool
 -      depends on SMP && !(X86_VISWS || X86_VOYAGER)
 -      default y
++      bool "Symmetric multi-processing support"
++      ---help---
++        This enables support for systems with more than one CPU. If you have
++        a system with only one CPU, like most personal computers, say N. If
++        you have a system with more than one CPU, say Y.
++
++        If you say N here, the kernel will run on single and multiprocessor
++        machines, but will use only one CPU of a multiprocessor machine. If
++        you say Y here, the kernel will run on many, but not all,
++        singleprocessor machines. On a singleprocessor machine, the kernel
++        will run faster if you say N here.
++
++        Note that if you say Y here and choose architecture "586" or
++        "Pentium" under "Processor family", the kernel will not work on 486
++        architectures. Similarly, multiprocessor kernels for the "PPro"
++        architecture may not work on all Pentium based boards.
++
++        People using multiprocessor machines who say Y here should also say
++        Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
++        Management" code will be disabled if you say Y here.
++
++        See also the <file:Documentation/smp.txt>,
++        <file:Documentation/i386/IO-APIC.txt>,
++        <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
++        <http://www.tldp.org/docs.html#howto>.
++
++        If you don't know what to do here, say N.
+ config NR_CPUS
+       int "Maximum number of CPUs (2-255)"
+       range 2 255
+       depends on SMP
+       default "32" if X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000
+       default "8"
+       help
+         This allows you to specify the maximum number of CPUs which this
+         kernel will support.  The maximum supported value is 255 and the
+         minimum value which makes sense is 2.
+         This is purely to save memory - each supported CPU adds
+         approximately eight kilobytes to the kernel image.
+ config SCHED_SMT
+       bool "SMT (Hyperthreading) scheduler support"
+       depends on SMP
+       default off
+       help
+         SMT scheduler support improves the CPU scheduler's decision making
+         when dealing with Intel Pentium 4 chips with HyperThreading at a
+         cost of slightly increased overhead in some places. If unsure say
+         N here.
+ config PREEMPT
+       bool "Preemptible Kernel"
+       help
+         This option reduces the latency of the kernel when reacting to
+         real-time or interactive events by allowing a low priority process to
+         be preempted even if it is in kernel mode executing a system call.
+         This allows applications to run more reliably even when the system is
+         under load.
+         Say Y here if you are building a kernel for a desktop, embedded
+         or real-time system.  Say N if you are unsure.
+ #config X86_TSC
+ #      bool
+ #     depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ
+ #      default y
+ #config X86_MCE
+ #      bool "Machine Check Exception"
+ #     depends on !X86_VOYAGER
+ #      ---help---
+ #        Machine Check Exception support allows the processor to notify the
+ #        kernel if it detects a problem (e.g. overheating, component failure).
+ #        The action the kernel takes depends on the severity of the problem,
+ #        ranging from a warning message on the console, to halting the machine.
+ #        Your processor must be a Pentium or newer to support this - check the
+ #        flags in /proc/cpuinfo for mce.  Note that some older Pentium systems
+ #        have a design flaw which leads to false MCE events - hence MCE is
+ #        disabled on all P5 processors, unless explicitly enabled with "mce"
+ #        as a boot argument.  Similarly, if MCE is built in and creates a
+ #        problem on some new non-standard machine, you can boot with "nomce"
+ #        to disable it.  MCE support simply ignores non-MCE processors like
+ #        the 386 and 486, so nearly everyone can say Y here.
+ #config X86_MCE_NONFATAL
+ #     tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4"
+ #      depends on X86_MCE
+ #      help
+ #        Enabling this feature starts a timer that triggers every 5 seconds which
+ #        will look at the machine check registers to see if anything happened.
+ #        Non-fatal problems automatically get corrected (but still logged).
+ #        Disable this if you don't want to see these messages.
+ #        Seeing the messages this option prints out may be indicative of dying hardware,
+ #        or out-of-spec (ie, overclocked) hardware.
+ #        This option only does something on certain CPUs.
+ #        (AMD Athlon/Duron and Intel Pentium 4)
+ #config X86_MCE_P4THERMAL
+ #      bool "check for P4 thermal throttling interrupt."
+ #      depends on X86_MCE && (X86_UP_APIC || SMP)
+ #      help
+ #        Enabling this feature will cause a message to be printed when the P4
+ #        enters thermal throttling.
+ #config MICROCODE
+ #      tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
+ #      ---help---
+ #        If you say Y here and also to "/dev file system support" in the
+ #        'File systems' section, you will be able to update the microcode on
+ #        Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II,
+ #        Pentium III, Pentium 4, Xeon etc.  You will obviously need the
+ #        actual microcode binary data itself which is not shipped with the
+ #        Linux kernel.
+ #
+ #        For latest news and information on obtaining all the required
+ #        ingredients for this driver, check:
+ #        <http://www.urbanmyth.org/microcode/>.
+ #
+ #        To compile this driver as a module, choose M here: the
+ #        module will be called microcode.
+ #config X86_MSR
+ #      tristate "/dev/cpu/*/msr - Model-specific register support"
+ #      help
+ #        This device gives privileged processes access to the x86
+ #        Model-Specific Registers (MSRs).  It is a character device with
+ #        major 202 and minors 0 to 31 for /dev/cpu/0/msr to /dev/cpu/31/msr.
+ #        MSR accesses are directed to a specific CPU on multi-processor
+ #        systems.
+ config X86_CPUID
+       tristate "/dev/cpu/*/cpuid - CPU information support"
+       help
+         This device gives processes access to the x86 CPUID instruction to
+         be executed on a specific processor.  It is a character device
+         with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
+         /dev/cpu/31/cpuid.
+ source "drivers/firmware/Kconfig"
+ choice
+       prompt "High Memory Support"
+       default NOHIGHMEM
+ config NOHIGHMEM
+       bool "off"
+       ---help---
+         Linux can use up to 64 Gigabytes of physical memory on x86 systems.
+         However, the address space of 32-bit x86 processors is only 4
+         Gigabytes large. That means that, if you have a large amount of
+         physical memory, not all of it can be "permanently mapped" by the
+         kernel. The physical memory that's not permanently mapped is called
+         "high memory".
+         If you are compiling a kernel which will never run on a machine with
+         more than 1 Gigabyte total physical RAM, answer "off" here (default
+         choice and suitable for most users). This will result in a "3GB/1GB"
+         split: 3GB are mapped so that each process sees a 3GB virtual memory
+         space and the remaining part of the 4GB virtual memory space is used
+         by the kernel to permanently map as much physical memory as
+         possible.
+         If the machine has between 1 and 4 Gigabytes physical RAM, then
+         answer "4GB" here.
+         If more than 4 Gigabytes is used then answer "64GB" here. This
+         selection turns Intel PAE (Physical Address Extension) mode on.
+         PAE implements 3-level paging on IA32 processors. PAE is fully
+         supported by Linux, PAE mode is implemented on all recent Intel
+         processors (Pentium Pro and better). NOTE: If you say "64GB" here,
+         then the kernel will not boot on CPUs that don't support PAE!
+         The actual amount of total physical memory will either be
+         auto detected or can be forced by using a kernel command line option
+         such as "mem=256M". (Try "man bootparam" or see the documentation of
+         your boot loader (lilo or loadlin) about how to pass options to the
+         kernel at boot time.)
+         If unsure, say "off".
+ config HIGHMEM4G
+       bool "4GB"
+       help
+         Select this if you have a 32-bit processor and between 1 and 4
+         gigabytes of physical RAM.
+ #config HIGHMEM64G
+ #     bool "64GB"
+ #     help
+ #       Select this if you have a 32-bit processor and more than 4
+ #       gigabytes of physical RAM.
+ endchoice
+ config HIGHMEM
+       bool
+       depends on HIGHMEM64G || HIGHMEM4G
+       default y
+ config X86_PAE
+       bool
+       depends on HIGHMEM64G
+       default y
+ # Common NUMA Features
+ config NUMA
+       bool "Numa Memory Allocation and Scheduler Support"
+       depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
+       default n if X86_PC
+       default y if (X86_NUMAQ || X86_SUMMIT)
+ # Need comments to help the hapless user trying to turn on NUMA support
+ comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support"
+       depends on X86_NUMAQ && (!HIGHMEM64G || !SMP)
+ comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
+       depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI)
+ config DISCONTIGMEM
+       bool
+       depends on NUMA
+       default y
+ config HAVE_ARCH_BOOTMEM_NODE
+       bool
+       depends on NUMA
+       default y
+ #config HIGHPTE
+ #     bool "Allocate 3rd-level pagetables from highmem"
+ #     depends on HIGHMEM4G || HIGHMEM64G
+ #     help
+ #       The VM uses one page table entry for each page of physical memory.
+ #       For systems with a lot of RAM, this can be wasteful of precious
+ #       low memory.  Setting this option will put user-space page table
+ #       entries in high memory.
+ config MTRR
+       bool
+       depends on XEN_PRIVILEGED_GUEST
+       default y
+ #config MTRR
+ #      bool "MTRR (Memory Type Range Register) support"
+ #      ---help---
+ #        On Intel P6 family processors (Pentium Pro, Pentium II and later)
+ #        the Memory Type Range Registers (MTRRs) may be used to control
+ #        processor access to memory ranges. This is most useful if you have
+ #        a video (VGA) card on a PCI or AGP bus. Enabling write-combining
+ #        allows bus write transfers to be combined into a larger transfer
+ #        before bursting over the PCI/AGP bus. This can increase performance
+ #        of image write operations 2.5 times or more. Saying Y here creates a
+ #        /proc/mtrr file which may be used to manipulate your processor's
+ #        MTRRs. Typically the X server should use this.
+ #
+ #        This code has a reasonably generic interface so that similar
+ #        control registers on other processors can be easily supported
+ #        as well:
+ #
+ #        The Cyrix 6x86, 6x86MX and M II processors have Address Range
+ #        Registers (ARRs) which provide a similar functionality to MTRRs. For
+ #        these, the ARRs are used to emulate the MTRRs.
+ #        The AMD K6-2 (stepping 8 and above) and K6-3 processors have two
+ #        MTRRs. The Centaur C6 (WinChip) has 8 MCRs, allowing
+ #        write-combining. All of these processors are supported by this code
+ #        and it makes sense to say Y here if you have one of them.
+ #
+ #        Saying Y here also fixes a problem with buggy SMP BIOSes which only
+ #        set the MTRRs for the boot CPU and not for the secondary CPUs. This
+ #        can lead to all sorts of problems, so it's good to say Y here.
+ #
+ #        You can safely say Y even if your machine doesn't have MTRRs, you'll
+ #        just add about 9 KB to your kernel.
+ #
+ #        See <file:Documentation/mtrr.txt> for more information.
+ config IRQBALANCE
+       bool "Enable kernel irq balancing"
+       depends on SMP && X86_IO_APIC
+       default y
+       help
+         The default yes will allow the kernel to do irq load balancing.
+         Saying no will keep the kernel from doing irq load balancing.
+ config HAVE_DEC_LOCK
+       bool
+       depends on (SMP || PREEMPT) && X86_CMPXCHG
+       default y
+ # turning this on wastes a bunch of space.
+ # Summit needs it only when NUMA is on
+ config BOOT_IOREMAP
+       bool
+       depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
+       default y
+ config REGPARM
+       bool "Use register arguments (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       default n
+       help
+       Compile the kernel with -mregparm=3. This uses an different ABI
+       and passes the first three arguments of a function call in registers.
+       This will probably break binary only modules.
+       This feature is only enabled for gcc-3.0 and later - earlier compilers
+       generate incorrect output with certain kernel constructs when
+       -mregparm=3 is used.
++config X86_LOCAL_APIC
++      bool
++      depends on (X86_VISWS || SMP) && !X86_VOYAGER
++      default n
++
+ if XEN_PHYSDEV_ACCESS
+ menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
+ config X86_VISWS_APIC
+       bool
+       depends on X86_VISWS
+       default y
 -config X86_HT
 -      bool
 -      depends on SMP && !(X86_VISWS || X86_VOYAGER)
 -      default y
++#config X86_IO_APIC
++#     bool
++#     depends on SMP && !(X86_VISWS || X86_VOYAGER)
++#     default y
+ config PCI
+       bool "PCI support" if !X86_VISWS
+       depends on !X86_VOYAGER
+       default y if X86_VISWS
+       help
+         Find out whether you have a PCI motherboard. PCI is the name of a
+         bus system, i.e. the way the CPU talks to the other stuff inside
+         your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+         VESA. If you have PCI, say Y, otherwise N.
+         The PCI-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>, contains valuable
+         information about which PCI hardware does work under Linux and which
+         doesn't.
+ #choice
+ #     prompt "PCI access mode"
+ #     depends on PCI && !X86_VISWS
+ #     default PCI_GOANY
+ #     ---help---
+ #       On PCI systems, the BIOS can be used to detect the PCI devices and
+ #       determine their configuration. However, some old PCI motherboards
+ #       have BIOS bugs and may crash if this is done. Also, some embedded
+ #       PCI-based systems don't have any BIOS at all. Linux can also try to
+ #       detect the PCI hardware directly without using the BIOS.
+ #
+ #       With this option, you can specify how Linux should detect the
+ #       PCI devices. If you choose "BIOS", the BIOS will be used,
+ #       if you choose "Direct", the BIOS won't be used, and if you
+ #       choose "MMConfig", then PCI Express MMCONFIG will be used.
+ #       If you choose "Any", the kernel will try MMCONFIG, then the
+ #       direct access method and falls back to the BIOS if that doesn't
+ #       work. If unsure, go with the default, which is "Any".
+ #
+ #config PCI_GOBIOS
+ #     bool "BIOS"
+ #
+ #config PCI_GOMMCONFIG
+ #     bool "MMConfig"
+ #
+ #config PCI_GODIRECT
+ #     bool "Direct"
+ #
+ #config PCI_GOANY
+ #     bool "Any"
+ #
+ #endchoice
+ #
+ #config PCI_BIOS
+ #     bool
+ #     depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
+ #     default y
+ #
+ #config PCI_DIRECT
+ #     bool
+ #     depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
+ #     default y
+ config PCI_DIRECT
+       bool
+       depends on PCI
+       default y
+ source "drivers/pci/Kconfig"
+ config ISA
+       bool "ISA support"
+       depends on !(X86_VOYAGER || X86_VISWS)
+       help
+         Find out whether you have ISA slots on your motherboard.  ISA is the
+         name of a bus system, i.e. the way the CPU talks to the other stuff
+         inside your box.  Other bus systems are PCI, EISA, MicroChannel
+         (MCA) or VESA.  ISA is an older system, now being displaced by PCI;
+         newer boards don't support it.  If you have ISA, say Y, otherwise N.
+ config EISA
+       bool "EISA support"
+       depends on ISA
+       ---help---
+         The Extended Industry Standard Architecture (EISA) bus was
+         developed as an open alternative to the IBM MicroChannel bus.
+         The EISA bus provided some of the features of the IBM MicroChannel
+         bus while maintaining backward compatibility with cards made for
+         the older ISA bus.  The EISA bus saw limited use between 1988 and
+         1995 when it was made obsolete by the PCI bus.
+         Say Y here if you are building a kernel for an EISA-based machine.
+         Otherwise, say N.
+ source "drivers/eisa/Kconfig"
+ config MCA
+       bool "MCA support"
+       depends on !(X86_VISWS || X86_VOYAGER)
+       help
+         MicroChannel Architecture is found in some IBM PS/2 machines and
+         laptops.  It is a bus system similar to PCI or ISA. See
+         <file:Documentation/mca.txt> (and especially the web page given
+         there) before attempting to build an MCA bus kernel.
+ config MCA
+       depends on X86_VOYAGER
+       default y if X86_VOYAGER
+ source "drivers/mca/Kconfig"
+ config SCx200
+       tristate "NatSemi SCx200 support"
+       depends on !X86_VOYAGER
+       help
+         This provides basic support for the National Semiconductor SCx200
+         processor.  Right now this is just a driver for the GPIO pins.
+         If you don't know what to do here, say N.
+         This support is also available as a module.  If compiled as a
+         module, it will be called scx200.
+ source "drivers/pcmcia/Kconfig"
+ source "drivers/pci/hotplug/Kconfig"
+ endmenu
+ endif
+ menu "Kernel hacking"
+ config DEBUG_KERNEL
+       bool "Kernel debugging"
+       help
+         Say Y here if you are developing drivers or trying to debug and
+         identify kernel problems.
+ config EARLY_PRINTK
+       bool "Early printk" if EMBEDDED
+       default y
+       help
+         Write kernel log output directly into the VGA buffer or to a serial
+         port.
+         This is useful for kernel debugging when your machine crashes very
+         early before the console code is initialized. For normal operation
+         it is not recommended because it looks ugly and doesn't cooperate
+         with klogd/syslogd or the X server. You should normally N here,
+         unless you want to debug such a crash.
+ config DEBUG_STACKOVERFLOW
+       bool "Check for stack overflows"
+       depends on DEBUG_KERNEL
+ config DEBUG_STACK_USAGE
+       bool "Stack utilization instrumentation"
+       depends on DEBUG_KERNEL
+       help
+         Enables the display of the minimum amount of free stack which each
+         task has ever had available in the sysrq-T and sysrq-P debug output.
+         This option will slow down process creation somewhat.
+ config DEBUG_SLAB
+       bool "Debug memory allocations"
+       depends on DEBUG_KERNEL
+       help
+         Say Y here to have the kernel do limited verification on memory
+         allocation as well as poisoning memory on free to catch use of freed
+         memory.
+ config MAGIC_SYSRQ
+       bool "Magic SysRq key"
+       depends on DEBUG_KERNEL
+       help
+         If you say Y here, you will have some control over the system even
+         if the system crashes for example during kernel debugging (e.g., you
+         will be able to flush the buffer cache to disk, reboot the system
+         immediately or dump some status information). This is accomplished
+         by pressing various keys while holding SysRq (Alt+PrintScreen). It
+         also works on a serial console (on PC hardware at least), if you
+         send a BREAK and then within 5 seconds a command keypress. The
+         keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
+         unless you really know what this hack does.
+ config DEBUG_SPINLOCK
+       bool "Spinlock debugging"
+       depends on DEBUG_KERNEL
+       help
+         Say Y here and build SMP to catch missing spinlock initialization
+         and certain other kinds of spinlock errors commonly made.  This is
+         best used in conjunction with the NMI watchdog so that spinlock
+         deadlocks are also debuggable.
+ config DEBUG_PAGEALLOC
+       bool "Page alloc debugging"
+       depends on DEBUG_KERNEL
+       help
+         Unmap pages from the kernel linear mapping after free_pages().
+         This results in a large slowdown, but helps to find certain types
+         of memory corruptions.
+ config DEBUG_HIGHMEM
+       bool "Highmem debugging"
+       depends on DEBUG_KERNEL && HIGHMEM
+       help
+         This options enables addition error checking for high memory systems.
+         Disable for production systems.
+ config DEBUG_INFO
+       bool "Compile the kernel with debug info"
+       depends on DEBUG_KERNEL
+       help
+           If you say Y here the resulting kernel image will include
+         debugging info resulting in a larger kernel image.
+         Say Y here only if you plan to use gdb to debug the kernel.
+         If you don't debug the kernel, you can say N.
+         
+ config DEBUG_SPINLOCK_SLEEP
+       bool "Sleep-inside-spinlock checking"
+       help
+         If you say Y here, various routines which may sleep will become very
+         noisy if they are called with a spinlock held.        
+ config FRAME_POINTER
+       bool "Compile the kernel with frame pointers"
+       help
+         If you say Y here the resulting kernel image will be slightly larger
+         and slower, but it will give very useful debugging information.
+         If you don't debug the kernel, you can say N, but we may not be able
+         to solve problems without frame pointers.
+ config 4KSTACKS
+       bool "Use 4Kb for kernel stacks instead of 8Kb"
+       help
+         If you say Y here the kernel will use a 4Kb stacksize for the
+         kernel stack attached to each process/thread. This facilitates
+         running more threads on a system and also reduces the pressure
+         on the VM subsystem for higher order allocations. This option
+         will also use IRQ stacks to compensate for the reduced stackspace.
+ config X86_FIND_SMP_CONFIG
+       bool
+       depends on X86_LOCAL_APIC || X86_VOYAGER
+       default y
+ config X86_MPPARSE
+       bool
+       depends on X86_LOCAL_APIC && !X86_VISWS
+       default y
+ endmenu
+ #
+ # Use the generic interrupt handling code in kernel/irq/:
+ #
+ config GENERIC_HARDIRQS
+       bool
+       default y
+ config GENERIC_IRQ_PROBE
+       bool
+       default y
+ config X86_SMP
+       bool
+       depends on SMP && !X86_VOYAGER
+       default y
++#config X86_HT
++#     bool
++#     depends on SMP && !(X86_VISWS || X86_VOYAGER)
++#     default y
+ config X86_BIOS_REBOOT
+       bool
+       depends on !(X86_VISWS || X86_VOYAGER)
+       default y
+ config X86_TRAMPOLINE
+       bool
+       depends on X86_SMP || (X86_VOYAGER && SMP)
+       default y
+ config PC
+       bool
+       depends on X86 && !EMBEDDED
+       default y
+ endmenu
index 0000000000000000000000000000000000000000,014f324cc181c3b26c361ccf2df3ae073245ebf3..e1bf116e4a49c98768d929026f0f4d8921b4fcc7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,90 +1,91 @@@
 -c-obj-$(CONFIG_X86_SMP)               += smp.o smpboot.o
 -c-obj-$(CONFIG_X86_TRAMPOLINE)        += trampoline.o
+ #
+ # Makefile for the linux kernel.
+ #
+ XENARCH       := $(subst ",,$(CONFIG_XENARCH))
+ CFLAGS        += -Iarch/$(XENARCH)/kernel
+ extra-y := head.o init_task.o
+ obj-y := process.o signal.o entry.o traps.o \
+               time.o ioport.o ldt.o setup.o \
+               pci-dma.o i386_ksyms.o
+ c-obj-y       := semaphore.o irq.o vm86.o \
+               ptrace.o sys_i386.o \
+               i387.o dmi_scan.o bootflag.o \
+               doublefault.o quirks.o
+ s-obj-y       :=
+ obj-y                         += cpu/
+ obj-y                         += timers/
+ c-obj-$(CONFIG_ACPI_BOOT)     += acpi/
+ #c-obj-$(CONFIG_X86_BIOS_REBOOT)      += reboot.o
+ c-obj-$(CONFIG_MCA)           += mca.o
+ c-obj-$(CONFIG_X86_MSR)               += msr.o
+ c-obj-$(CONFIG_X86_CPUID)     += cpuid.o
+ c-obj-$(CONFIG_MICROCODE)     += microcode.o
+ c-obj-$(CONFIG_APM)           += apm.o
 -c-obj-$(CONFIG_X86_LOCAL_APIC)        += apic.o nmi.o
++obj-$(CONFIG_X86_SMP)         += smp.o smpboot.o
++#obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
+ c-obj-$(CONFIG_X86_MPPARSE)   += mpparse.o
++#obj-$(CONFIG_X86_LOCAL_APIC) += apic.o
++c-obj-$(CONFIG_X86_LOCAL_APIC)        += nmi.o
+ c-obj-$(CONFIG_X86_IO_APIC)   += io_apic.o
+ c-obj-$(CONFIG_X86_NUMAQ)     += numaq.o
+ c-obj-$(CONFIG_X86_SUMMIT_NUMA)       += summit.o
+ c-obj-$(CONFIG_MODULES)               += module.o
+ c-obj-y                               += sysenter.o
+ obj-y                         += vsyscall.o
+ c-obj-$(CONFIG_ACPI_SRAT)     += srat.o
+ c-obj-$(CONFIG_HPET_TIMER)    += time_hpet.o
+ c-obj-$(CONFIG_EFI)           += efi.o efi_stub.o
+ c-obj-$(CONFIG_EARLY_PRINTK)  += early_printk.o
+ EXTRA_AFLAGS   := -traditional
+ c-obj-$(CONFIG_SCx200)                += scx200.o
+ # vsyscall.o contains the vsyscall DSO images as __initdata.
+ # We must build both images before we can assemble it.
+ # Note: kbuild does not track this dependency due to usage of .incbin
+ $(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so
+ targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so)
+ # The DSO images are built using a special linker script.
+ quiet_cmd_syscall = SYSCALL $@
+       cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
+                         -Wl,-T,$(filter-out FORCE,$^) -o $@
+ vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1
+ SYSCFLAGS_vsyscall-sysenter.so        = $(vsyscall-flags)
+ SYSCFLAGS_vsyscall-int80.so   = $(vsyscall-flags)
+ $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \
+ $(obj)/vsyscall-%.so: $(obj)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
+       $(call if_changed,syscall)
+ # We also create a special relocatable object that should mirror the symbol
+ # table and layout of the linked DSO.  With ld -R we can then refer to
+ # these symbols in the kernel code rather than hand-coded addresses.
+ extra-y += vsyscall-syms.o
+ $(obj)/built-in.o: $(obj)/vsyscall-syms.o
+ $(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o
+ SYSCFLAGS_vsyscall-syms.o = -r
+ $(obj)/vsyscall-syms.o: $(obj)/vsyscall.lds $(obj)/vsyscall-sysenter.o FORCE
+       $(call if_changed,syscall)
+ c-link        := init_task.o
+ s-link        := vsyscall-int80.o vsyscall-sysenter.o vsyscall-sigreturn.o
+ $(patsubst %.o,$(obj)/%.c,$(c-obj-y) $(c-link)) $(patsubst %.o,$(obj)/%.S,$(s-obj-y) $(s-link)):
+       @ln -fsn $(srctree)/arch/i386/kernel/$(notdir $@) $@
+ $(obj)/vsyscall-int80.S: $(obj)/vsyscall-sigreturn.S
+ obj-y += $(c-obj-y) $(s-obj-y)
+ clean-files += $(patsubst %.o,%.c,$(c-obj-y) $(c-obj-) $(c-link))
+ clean-files += $(patsubst %.o,%.S,$(s-obj-y) $(s-obj-) $(s-link))
index 0000000000000000000000000000000000000000,a29a7f4e97250fa6dbd80171a865e553fc67750d..750524cfcfc3ef0a3c71a22eb4985e89b5902bed
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,606 +1,601 @@@
 -      /*
 -       * Initialize the per-CPU GDT with the boot GDT,
 -       * and set up the GDT descriptor:
 -       */
 -      if (cpu) {
 -              cpu_gdt_descr[cpu].size = GDT_SIZE;
 -              cpu_gdt_descr[cpu].address = 0; /* XXXcl alloc page */
 -              BUG();          /* XXXcl SMP */
 -              memcpy((void *)cpu_gdt_descr[cpu].address,
 -                  (void *)cpu_gdt_descr[0].address, GDT_SIZE);
 -      }
+ #include <linux/init.h>
+ #include <linux/string.h>
+ #include <linux/delay.h>
+ #include <linux/smp.h>
+ #include <linux/module.h>
+ #include <linux/percpu.h>
+ #include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/msr.h>
+ #include <asm/io.h>
+ #include <asm/mmu_context.h>
+ #include <asm-xen/hypervisor.h>
+ #include "cpu.h"
+ DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
+ EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
+ static int cachesize_override __initdata = -1;
+ static int disable_x86_fxsr __initdata = 0;
+ static int disable_x86_serial_nr __initdata = 1;
+ struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
+ extern void mcheck_init(struct cpuinfo_x86 *c);
+ extern void machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c);
+ extern int disable_pse;
+ static void default_init(struct cpuinfo_x86 * c)
+ {
+       /* Not much we can do here... */
+       /* Check if at least it has cpuid */
+       if (c->cpuid_level == -1) {
+               /* No cpuid. It must be an ancient CPU */
+               if (c->x86 == 4)
+                       strcpy(c->x86_model_id, "486");
+               else if (c->x86 == 3)
+                       strcpy(c->x86_model_id, "386");
+       }
+ }
+ static struct cpu_dev default_cpu = {
+       .c_init = default_init,
+ };
+ static struct cpu_dev * this_cpu = &default_cpu;
+ static int __init cachesize_setup(char *str)
+ {
+       get_option (&str, &cachesize_override);
+       return 1;
+ }
+ __setup("cachesize=", cachesize_setup);
+ int __init get_model_name(struct cpuinfo_x86 *c)
+ {
+       unsigned int *v;
+       char *p, *q;
+       if (cpuid_eax(0x80000000) < 0x80000004)
+               return 0;
+       v = (unsigned int *) c->x86_model_id;
+       cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+       cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+       cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+       c->x86_model_id[48] = 0;
+       /* Intel chips right-justify this string for some dumb reason;
+          undo that brain damage */
+       p = q = &c->x86_model_id[0];
+       while ( *p == ' ' )
+            p++;
+       if ( p != q ) {
+            while ( *p )
+                 *q++ = *p++;
+            while ( q <= &c->x86_model_id[48] )
+                 *q++ = '\0';  /* Zero-pad the rest */
+       }
+       return 1;
+ }
+ void __init display_cacheinfo(struct cpuinfo_x86 *c)
+ {
+       unsigned int n, dummy, ecx, edx, l2size;
+       n = cpuid_eax(0x80000000);
+       if (n >= 0x80000005) {
+               cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
+               printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
+                       edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
+               c->x86_cache_size=(ecx>>24)+(edx>>24);  
+       }
+       if (n < 0x80000006)     /* Some chips just has a large L1. */
+               return;
+       ecx = cpuid_ecx(0x80000006);
+       l2size = ecx >> 16;
+       
+       /* do processor-specific cache resizing */
+       if (this_cpu->c_size_cache)
+               l2size = this_cpu->c_size_cache(c,l2size);
+       /* Allow user to override all this if necessary. */
+       if (cachesize_override != -1)
+               l2size = cachesize_override;
+       if ( l2size == 0 )
+               return;         /* Again, no L2 cache is possible */
+       c->x86_cache_size = l2size;
+       printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
+              l2size, ecx & 0xFF);
+ }
+ /* Naming convention should be: <Name> [(<Codename>)] */
+ /* This table only is used unless init_<vendor>() below doesn't set it; */
+ /* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */
+ /* Look up CPU names by table lookup. */
+ static char __init *table_lookup_model(struct cpuinfo_x86 *c)
+ {
+       struct cpu_model_info *info;
+       if ( c->x86_model >= 16 )
+               return NULL;    /* Range check */
+       if (!this_cpu)
+               return NULL;
+       info = this_cpu->c_models;
+       while (info && info->family) {
+               if (info->family == c->x86)
+                       return info->model_names[c->x86_model];
+               info++;
+       }
+       return NULL;            /* Not found */
+ }
+ void __init get_cpu_vendor(struct cpuinfo_x86 *c, int early)
+ {
+       char *v = c->x86_vendor_id;
+       int i;
+       for (i = 0; i < X86_VENDOR_NUM; i++) {
+               if (cpu_devs[i]) {
+                       if (!strcmp(v,cpu_devs[i]->c_ident[0]) ||
+                           (cpu_devs[i]->c_ident[1] && 
+                            !strcmp(v,cpu_devs[i]->c_ident[1]))) {
+                               c->x86_vendor = i;
+                               if (!early)
+                                       this_cpu = cpu_devs[i];
+                               break;
+                       }
+               }
+       }
+ }
+ static int __init x86_fxsr_setup(char * s)
+ {
+       disable_x86_fxsr = 1;
+       return 1;
+ }
+ __setup("nofxsr", x86_fxsr_setup);
+ /* Standard macro to see if a specific flag is changeable */
+ static inline int flag_is_changeable_p(u32 flag)
+ {
+       u32 f1, f2;
+       asm("pushfl\n\t"
+           "pushfl\n\t"
+           "popl %0\n\t"
+           "movl %0,%1\n\t"
+           "xorl %2,%0\n\t"
+           "pushl %0\n\t"
+           "popfl\n\t"
+           "pushfl\n\t"
+           "popl %0\n\t"
+           "popfl\n\t"
+           : "=&r" (f1), "=&r" (f2)
+           : "ir" (flag));
+       return ((f1^f2) & flag) != 0;
+ }
+ /* Probe for the CPUID instruction */
+ int __init have_cpuid_p(void)
+ {
+       return flag_is_changeable_p(X86_EFLAGS_ID);
+ }
+ /* Do minimum CPU detection early.
+    Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
+    The others are not touched to avoid unwanted side effects. */
+ void __init early_cpu_detect(void)
+ {
+       struct cpuinfo_x86 *c = &boot_cpu_data;
+       c->x86_cache_alignment = 32;
+       if (!have_cpuid_p())
+               return;
+       /* Get vendor name */
+       cpuid(0x00000000, &c->cpuid_level,
+             (int *)&c->x86_vendor_id[0],
+             (int *)&c->x86_vendor_id[8],
+             (int *)&c->x86_vendor_id[4]);
+       get_cpu_vendor(c, 1);
+       c->x86 = 4;
+       if (c->cpuid_level >= 0x00000001) {
+               u32 junk, tfms, cap0, misc;
+               cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
+               c->x86 = (tfms >> 8) & 15;
+               c->x86_model = (tfms >> 4) & 15;
+               if (c->x86 == 0xf) {
+                       c->x86 += (tfms >> 20) & 0xff;
+                       c->x86_model += ((tfms >> 16) & 0xF) << 4;
+               }
+               c->x86_mask = tfms & 15;
+               if (cap0 & (1<<19))
+                       c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
+       }
+       early_intel_workaround(c);
+ }
+ void __init generic_identify(struct cpuinfo_x86 * c)
+ {
+       u32 tfms, xlvl;
+       int junk;
+       if (have_cpuid_p()) {
+               /* Get vendor name */
+               cpuid(0x00000000, &c->cpuid_level,
+                     (int *)&c->x86_vendor_id[0],
+                     (int *)&c->x86_vendor_id[8],
+                     (int *)&c->x86_vendor_id[4]);
+               
+               get_cpu_vendor(c, 0);
+               /* Initialize the standard set of capabilities */
+               /* Note that the vendor-specific code below might override */
+       
+               /* Intel-defined flags: level 0x00000001 */
+               if ( c->cpuid_level >= 0x00000001 ) {
+                       u32 capability, excap;
+                       cpuid(0x00000001, &tfms, &junk, &excap, &capability);
+                       c->x86_capability[0] = capability;
+                       c->x86_capability[4] = excap;
+                       c->x86 = (tfms >> 8) & 15;
+                       c->x86_model = (tfms >> 4) & 15;
+                       if (c->x86 == 0xf) {
+                               c->x86 += (tfms >> 20) & 0xff;
+                               c->x86_model += ((tfms >> 16) & 0xF) << 4;
+                       } 
+                       c->x86_mask = tfms & 15;
+               } else {
+                       /* Have CPUID level 0 only - unheard of */
+                       c->x86 = 4;
+               }
+               /* AMD-defined flags: level 0x80000001 */
+               xlvl = cpuid_eax(0x80000000);
+               if ( (xlvl & 0xffff0000) == 0x80000000 ) {
+                       if ( xlvl >= 0x80000001 )
+                               c->x86_capability[1] = cpuid_edx(0x80000001);
+                       if ( xlvl >= 0x80000004 )
+                               get_model_name(c); /* Default name */
+               }
+       }
+ }
+ static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+ {
+       if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) {
+               /* Disable processor serial number */
+               unsigned long lo,hi;
+               rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
+               lo |= 0x200000;
+               wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
+               printk(KERN_NOTICE "CPU serial number disabled.\n");
+               clear_bit(X86_FEATURE_PN, c->x86_capability);
+               /* Disabling the serial number may affect the cpuid level */
+               c->cpuid_level = cpuid_eax(0);
+       }
+ }
+ static int __init x86_serial_nr_setup(char *s)
+ {
+       disable_x86_serial_nr = 0;
+       return 1;
+ }
+ __setup("serialnumber", x86_serial_nr_setup);
+ /*
+  * This does the hard work of actually picking apart the CPU stuff...
+  */
+ void __init identify_cpu(struct cpuinfo_x86 *c)
+ {
+       int i;
+       c->loops_per_jiffy = loops_per_jiffy;
+       c->x86_cache_size = -1;
+       c->x86_vendor = X86_VENDOR_UNKNOWN;
+       c->cpuid_level = -1;    /* CPUID not detected */
+       c->x86_model = c->x86_mask = 0; /* So far unknown... */
+       c->x86_vendor_id[0] = '\0'; /* Unset */
+       c->x86_model_id[0] = '\0';  /* Unset */
+       memset(&c->x86_capability, 0, sizeof c->x86_capability);
+       if (!have_cpuid_p()) {
+               /* First of all, decide if this is a 486 or higher */
+               /* It's a 486 if we can modify the AC flag */
+               if ( flag_is_changeable_p(X86_EFLAGS_AC) )
+                       c->x86 = 4;
+               else
+                       c->x86 = 3;
+       }
+       generic_identify(c);
+       printk(KERN_DEBUG "CPU: After generic identify, caps: %08lx %08lx %08lx %08lx\n",
+               c->x86_capability[0],
+               c->x86_capability[1],
+               c->x86_capability[2],
+               c->x86_capability[3]);
+       if (this_cpu->c_identify) {
+               this_cpu->c_identify(c);
+       printk(KERN_DEBUG "CPU: After vendor identify, caps:  %08lx %08lx %08lx %08lx\n",
+               c->x86_capability[0],
+               c->x86_capability[1],
+               c->x86_capability[2],
+               c->x86_capability[3]);
+ }
+       /*
+        * Vendor-specific initialization.  In this section we
+        * canonicalize the feature flags, meaning if there are
+        * features a certain CPU supports which CPUID doesn't
+        * tell us, CPUID claiming incorrect flags, or other bugs,
+        * we handle them here.
+        *
+        * At the end of this section, c->x86_capability better
+        * indicate the features this CPU genuinely supports!
+        */
+       if (this_cpu->c_init)
+               this_cpu->c_init(c);
+       /* Disable the PN if appropriate */
+       squash_the_stupid_serial_number(c);
+       /*
+        * The vendor-specific functions might have changed features.  Now
+        * we do "generic changes."
+        */
+       /* TSC disabled? */
+       if ( tsc_disable )
+               clear_bit(X86_FEATURE_TSC, c->x86_capability);
+       /* FXSR disabled? */
+       if (disable_x86_fxsr) {
+               clear_bit(X86_FEATURE_FXSR, c->x86_capability);
+               clear_bit(X86_FEATURE_XMM, c->x86_capability);
+       }
+       if (disable_pse)
+               clear_bit(X86_FEATURE_PSE, c->x86_capability);
+       /* If the model name is still unset, do table lookup. */
+       if ( !c->x86_model_id[0] ) {
+               char *p;
+               p = table_lookup_model(c);
+               if ( p )
+                       strcpy(c->x86_model_id, p);
+               else
+                       /* Last resort... */
+                       sprintf(c->x86_model_id, "%02x/%02x",
+                               c->x86_vendor, c->x86_model);
+       }
+       machine_specific_modify_cpu_capabilities(c);
+       /* Now the feature flags better reflect actual CPU features! */
+       printk(KERN_DEBUG "CPU: After all inits, caps:        %08lx %08lx %08lx %08lx\n",
+              c->x86_capability[0],
+              c->x86_capability[1],
+              c->x86_capability[2],
+              c->x86_capability[3]);
+       /*
+        * On SMP, boot_cpu_data holds the common feature set between
+        * all CPUs; so make sure that we indicate which features are
+        * common between the CPUs.  The first time this routine gets
+        * executed, c == &boot_cpu_data.
+        */
+       if ( c != &boot_cpu_data ) {
+               /* AND the already accumulated flags with these */
+               for ( i = 0 ; i < NCAPINTS ; i++ )
+                       boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+       }
+       /* Init Machine Check Exception if available. */
+ #ifdef CONFIG_X86_MCE
+       mcheck_init(c);
+ #endif
+ }
+ /*
+  *    Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
+  */
+  
+ void __init dodgy_tsc(void)
+ {
+       if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) ||
+           ( boot_cpu_data.x86_vendor == X86_VENDOR_NSC   ))
+               cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data);
+ }
+ void __init print_cpu_info(struct cpuinfo_x86 *c)
+ {
+       char *vendor = NULL;
+       if (c->x86_vendor < X86_VENDOR_NUM)
+               vendor = this_cpu->c_vendor;
+       else if (c->cpuid_level >= 0)
+               vendor = c->x86_vendor_id;
+       if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor)))
+               printk("%s ", vendor);
+       if (!c->x86_model_id[0])
+               printk("%d86", c->x86);
+       else
+               printk("%s", c->x86_model_id);
+       if (c->x86_mask || c->cpuid_level >= 0) 
+               printk(" stepping %02x\n", c->x86_mask);
+       else
+               printk("\n");
+ }
+ unsigned long cpu_initialized __initdata = 0;
+ /* This is hacky. :)
+  * We're emulating future behavior.
+  * In the future, the cpu-specific init functions will be called implicitly
+  * via the magic of initcalls.
+  * They will insert themselves into the cpu_devs structure.
+  * Then, when cpu_init() is called, we can just iterate over that array.
+  */
+ extern int intel_cpu_init(void);
+ extern int cyrix_init_cpu(void);
+ extern int nsc_init_cpu(void);
+ extern int amd_init_cpu(void);
+ extern int centaur_init_cpu(void);
+ extern int transmeta_init_cpu(void);
+ extern int rise_init_cpu(void);
+ extern int nexgen_init_cpu(void);
+ extern int umc_init_cpu(void);
+ void early_cpu_detect(void);
+ void __init early_cpu_init(void)
+ {
+       intel_cpu_init();
+       cyrix_init_cpu();
+       nsc_init_cpu();
+       amd_init_cpu();
+       centaur_init_cpu();
+       transmeta_init_cpu();
+       rise_init_cpu();
+       nexgen_init_cpu();
+       umc_init_cpu();
+       early_cpu_detect();
+ #ifdef CONFIG_DEBUG_PAGEALLOC
+       /* pse is not compatible with on-the-fly unmapping,
+        * disable it even if the cpus claim to support it.
+        */
+       clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+       disable_pse = 1;
+ #endif
+ }
+ void __init cpu_gdt_init(struct Xgt_desc_struct *gdt_descr)
+ {
+       unsigned long frames[gdt_descr->size >> PAGE_SHIFT];
+       unsigned long va;
+       int f;
+       for (va = gdt_descr->address, f = 0;
+            va < gdt_descr->address + gdt_descr->size;
+            va += PAGE_SIZE, f++) {
+               frames[f] = virt_to_machine(va) >> PAGE_SHIFT;
+               make_page_readonly((void *)va);
+       }
+       flush_page_update_queue();
+       if (HYPERVISOR_set_gdt(frames, gdt_descr->size / 8))
+               BUG();
+       lgdt_finish();
+ }
+ /*
+  * cpu_init() initializes state that is per-CPU. Some data is already
+  * initialized (naturally) in the bootstrap process, such as the GDT
+  * and IDT. We reload them nevertheless, this function acts as a
+  * 'CPU state barrier', nothing should get across.
+  */
+ void __init cpu_init (void)
+ {
+       int cpu = smp_processor_id();
+       struct tss_struct * t = &per_cpu(init_tss, cpu);
+       struct thread_struct *thread = &current->thread;
+       if (test_and_set_bit(cpu, &cpu_initialized)) {
+               printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
+               for (;;) local_irq_enable();
+       }
+       printk(KERN_INFO "Initializing CPU#%d\n", cpu);
+       if (cpu_has_vme || cpu_has_de)
+               clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
+       if (tsc_disable && cpu_has_tsc) {
+               printk(KERN_NOTICE "Disabling TSC...\n");
+               /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/
+               clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
+               set_in_cr4(X86_CR4_TSD);
+       }
+       /*
+        * Set up the per-thread TLS descriptor cache:
+        */
+       memcpy(thread->tls_array, &get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN],
+           GDT_ENTRY_TLS_ENTRIES * 8);
+       cpu_gdt_init(&cpu_gdt_descr[cpu]);
+       /*
+        * Delete NT
+        */
+       __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
+       /*
+        * Set up and load the per-CPU TSS and LDT
+        */
+       atomic_inc(&init_mm.mm_count);
+       current->active_mm = &init_mm;
+       if (current->mm)
+               BUG();
+       enter_lazy_tlb(&init_mm, current);
+       load_esp0(t, thread);
+       load_LDT(&init_mm.context);
+       flush_page_update_queue();
+       /* Clear %fs and %gs. */
+       asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
+       /* Clear all 6 debug registers: */
+ #define CD(register) HYPERVISOR_set_debugreg(register, 0)
+       CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
+ #undef CD
+       /*
+        * Force FPU initialization:
+        */
+       current_thread_info()->status = 0;
+       current->used_math = 0;
+       mxcsr_feature_mask_init();
+ }
++
++
++int get_smp_processor_id(void)
++{
++      return smp_processor_id();
++}
index 0000000000000000000000000000000000000000,321f89e3d4a05d8520409d743b78ddc110923a01..6a13d005c15a687c54ca8b09e5cdc24a183dd50a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1034 +1,1068 @@@
+ /*
+  *  linux/arch/i386/entry.S
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  */
+ /*
+  * entry.S contains the system-call and fault low-level handling routines.
+  * This also contains the timer-interrupt handler, as well as all interrupts
+  * and faults that can result in a task-switch.
+  *
+  * NOTE: This code handles signal-recognition, which happens every time
+  * after a timer-interrupt and after each system call.
+  *
+  * I changed all the .align's to 4 (16 byte alignment), as that's faster
+  * on a 486.
+  *
+  * Stack layout in 'ret_from_system_call':
+  *    ptrace needs to have all regs on the stack.
+  *    if the order here is changed, it needs to be
+  *    updated in fork.c:copy_process, signal.c:do_signal,
+  *    ptrace.c and ptrace.h
+  *
+  *     0(%esp) - %ebx
+  *     4(%esp) - %ecx
+  *     8(%esp) - %edx
+  *       C(%esp) - %esi
+  *    10(%esp) - %edi
+  *    14(%esp) - %ebp
+  *    18(%esp) - %eax
+  *    1C(%esp) - %ds
+  *    20(%esp) - %es
+  *    24(%esp) - orig_eax
+  *    28(%esp) - %eip
+  *    2C(%esp) - %cs
+  *    30(%esp) - %eflags
+  *    34(%esp) - %oldesp
+  *    38(%esp) - %oldss
+  *
+  * "current" is in register %ebx during any slow entries.
+  */
+ #include <linux/config.h>
+ #include <linux/linkage.h>
+ #include <asm/thread_info.h>
+ #include <asm/errno.h>
+ #include <asm/segment.h>
+ #include <asm/smp.h>
+ #include <asm/page.h>
+ #include "irq_vectors.h"
+ #include <asm-xen/xen-public/xen.h>
+ #define nr_syscalls ((syscall_table_size)/4)
+ EBX           = 0x00
+ ECX           = 0x04
+ EDX           = 0x08
+ ESI           = 0x0C
+ EDI           = 0x10
+ EBP           = 0x14
+ EAX           = 0x18
+ DS            = 0x1C
+ ES            = 0x20
+ ORIG_EAX      = 0x24
+ EIP           = 0x28
+ CS            = 0x2C
+ EVENT_MASK    = 0x2E
+ EFLAGS                = 0x30
+ OLDESP                = 0x34
+ OLDSS         = 0x38
+ CF_MASK               = 0x00000001
+ TF_MASK               = 0x00000100
+ IF_MASK               = 0x00000200
+ DF_MASK               = 0x00000400 
+ NT_MASK               = 0x00004000
+ VM_MASK               = 0x00020000
+ /* Offsets into shared_info_t. */
+ #define evtchn_upcall_pending         /* 0 */
+ #define evtchn_upcall_mask            1
++#define sizeof_vcpu_shift             3
++
++#ifdef CONFIG_SMP
++#define XEN_GET_VCPU_INFO(reg)
++#define preempt_disable(reg)  incl TI_preempt_count(reg)
++#define preempt_enable(reg)   decl TI_preempt_count(reg)
++#define XEN_LOCK_VCPU_INFO_SMP(reg) preempt_disable(%ebp)             ; \
++                              movl TI_cpu(%ebp),reg                   ; \
++                              shl  $sizeof_vcpu_shift,reg             ; \
++                              addl HYPERVISOR_shared_info,reg
++#define XEN_UNLOCK_VCPU_INFO_SMP(reg) preempt_enable(%ebp)
++#define XEN_UNLOCK_VCPU_INFO_SMP_fixup .byte 0x00,0x00,0x00
++#define XEN_BLOCK_EVENTS(reg) XEN_LOCK_VCPU_INFO_SMP(reg)             ; \
++                              movb $1,evtchn_upcall_mask(reg)         ; \
++                              XEN_UNLOCK_VCPU_INFO_SMP(reg)
++#define XEN_UNBLOCK_EVENTS(reg)       XEN_LOCK_VCPU_INFO_SMP(reg)             ; \
++                              movb $0,evtchn_upcall_mask(reg)         ; \
++                              XEN_UNLOCK_VCPU_INFO_SMP(reg)
++#define XEN_SAVE_UPCALL_MASK(reg,tmp,off) GET_THREAD_INFO(%ebp)               ; \
++                              XEN_LOCK_VCPU_INFO_SMP(reg)             ; \
++                              movb evtchn_upcall_mask(reg), tmp       ; \
++                              movb tmp, off(%esp)                     ; \
++                              XEN_UNLOCK_VCPU_INFO_SMP(reg)
++#else
+ #define XEN_GET_VCPU_INFO(reg)        movl HYPERVISOR_shared_info,reg
++#define XEN_LOCK_VCPU_INFO_SMP(reg)
++#define XEN_UNLOCK_VCPU_INFO_SMP(reg)
++#define XEN_UNLOCK_VCPU_INFO_SMP_fixup
+ #define XEN_BLOCK_EVENTS(reg) movb $1,evtchn_upcall_mask(reg)
+ #define XEN_UNBLOCK_EVENTS(reg)       movb $0,evtchn_upcall_mask(reg)
+ #define XEN_SAVE_UPCALL_MASK(reg,tmp,off) \
+       movb evtchn_upcall_mask(reg), tmp; \
+       movb tmp, off(%esp)
++#endif
+ #define XEN_TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(reg)
+ #ifdef CONFIG_PREEMPT
+ #define preempt_stop          XEN_BLOCK_EVENTS(%esi)
+ #else
+ #define preempt_stop
+ #define resume_kernel         restore_all
+ #endif
+ #define SAVE_ALL_NO_EVENTMASK \
+       cld; \
+       pushl %es; \
+       pushl %ds; \
+       pushl %eax; \
+       pushl %ebp; \
+       pushl %edi; \
+       pushl %esi; \
+       pushl %edx; \
+       pushl %ecx; \
+       pushl %ebx; \
+       movl $(__USER_DS), %edx; \
+       movl %edx, %ds; \
+       movl %edx, %es;
+ #define SAVE_ALL \
+       SAVE_ALL_NO_EVENTMASK; \
+       XEN_GET_VCPU_INFO(%esi); \
+       XEN_SAVE_UPCALL_MASK(%esi,%dl,EVENT_MASK)
+ #define RESTORE_INT_REGS \
+       popl %ebx;      \
+       popl %ecx;      \
+       popl %edx;      \
+       popl %esi;      \
+       popl %edi;      \
+       popl %ebp;      \
+       popl %eax
+ #define RESTORE_REGS  \
+       RESTORE_INT_REGS; \
+ 1:    popl %ds;       \
+ 2:    popl %es;       \
+ .section .fixup,"ax"; \
+ 3:    movl $0,(%esp); \
+       jmp 1b;         \
+ 4:    movl $0,(%esp); \
+       jmp 2b;         \
+ .previous;            \
+ .section __ex_table,"a";\
+       .align 4;       \
+       .long 1b,3b;    \
+       .long 2b,4b;    \
+ .previous
+ #define RESTORE_ALL   \
+       RESTORE_REGS    \
+       addl $4, %esp;  \
+ 1:    iret;           \
+ .section .fixup,"ax";   \
+ 2:    movl $(__USER_DS), %edx; \
+       movl %edx, %ds; \
+       movl %edx, %es; \
+       movl $11,%eax;  \
+       call do_exit;   \
+ .previous;            \
+ .section __ex_table,"a";\
+       .align 4;       \
+       .long 1b,2b;    \
+ .previous
+ ENTRY(ret_from_fork)
+       pushl %eax
+       call schedule_tail
+       GET_THREAD_INFO(%ebp)
+       popl %eax
+       XEN_GET_VCPU_INFO(%esi)
+       jmp syscall_exit
+ /*
+  * Return to user mode is not as complex as all this looks,
+  * but we want the default path for a system call return to
+  * go as quickly as possible which is why some of this is
+  * less clear than it otherwise should be.
+  */
+       # userspace resumption stub bypassing syscall exit tracing
+       ALIGN
+ ret_from_exception:
+       preempt_stop
+ ret_from_intr:
+       GET_THREAD_INFO(%ebp)
+       movl EFLAGS(%esp), %eax         # mix EFLAGS and CS
+       movb CS(%esp), %al
+       testl $(VM_MASK | 2), %eax
+       jz resume_kernel                # returning to kernel or vm86-space
+ ENTRY(resume_userspace)
+       XEN_GET_VCPU_INFO(%esi)
+       XEN_BLOCK_EVENTS(%esi)          # make sure we don't miss an interrupt
+                                       # setting need_resched or sigpending
+                                       # between sampling and the iret
+       movl TI_flags(%ebp), %ecx
+       andl $_TIF_WORK_MASK, %ecx      # is there any work to be done on
+                                       # int/exception return?
+       jne work_pending
+       jmp restore_all
+ #ifdef CONFIG_PREEMPT
+ ENTRY(resume_kernel)
+       XEN_GET_VCPU_INFO(%esi)
+       cmpl $0,TI_preempt_count(%ebp)  # non-zero preempt_count ?
+       jnz restore_all
+ need_resched:
+       movl TI_flags(%ebp), %ecx       # need_resched set ?
+       testb $_TIF_NEED_RESCHED, %cl
+       jz restore_all
+       testb $0xFF,EVENT_MASK(%esp)    # interrupts off (exception path) ?
+       jnz restore_all
+       movl $PREEMPT_ACTIVE,TI_preempt_count(%ebp)
+       XEN_UNBLOCK_EVENTS(%esi)
+       call schedule
+       XEN_BLOCK_EVENTS(%esi)
+       movl $0,TI_preempt_count(%ebp)
+       jmp need_resched
+ #endif
+ /* SYSENTER_RETURN points to after the "sysenter" instruction in
+    the vsyscall page.  See vsyscall-sysentry.S, which defines the symbol.  */
+       # sysenter call handler stub
+ ENTRY(sysenter_entry)
+       movl TSS_sysenter_esp0(%esp),%esp
+ sysenter_past_esp:
+       sti
+       pushl $(__USER_DS)
+       pushl %ebp
+       pushfl
+       pushl $(__USER_CS)
+       pushl $SYSENTER_RETURN
+ /*
+  * Load the potential sixth argument from user stack.
+  * Careful about security.
+  */
+       cmpl $__PAGE_OFFSET-3,%ebp
+       jae syscall_fault
+ 1:    movl (%ebp),%ebp
+ .section __ex_table,"a"
+       .align 4
+       .long 1b,syscall_fault
+ .previous
+       pushl %eax
+       SAVE_ALL
+       GET_THREAD_INFO(%ebp)
+       testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+       jnz syscall_trace_entry
+       cmpl $(nr_syscalls), %eax
+       jae syscall_badsys
+       call *sys_call_table(,%eax,4)
+       movl %eax,EAX(%esp)
+       cli
+       movl TI_flags(%ebp), %ecx
+       testw $_TIF_ALLWORK_MASK, %cx
+       jne syscall_exit_work
+ /* if something modifies registers it must also disable sysexit */
+       movl EIP(%esp), %edx
+       movl OLDESP(%esp), %ecx
+       xorl %ebp,%ebp
+       sti
+       sysexit
+       # system call handler stub
+ ENTRY(system_call)
+       pushl %eax                      # save orig_eax
+       SAVE_ALL
+       GET_THREAD_INFO(%ebp)
+                                       # system call tracing in operation
+       testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+       jnz syscall_trace_entry
+       cmpl $(nr_syscalls), %eax
+       jae syscall_badsys
+ syscall_call:
+       call *sys_call_table(,%eax,4)
+       movl %eax,EAX(%esp)             # store the return value
+ syscall_exit:
+       XEN_BLOCK_EVENTS(%esi)          # make sure we don't miss an interrupt
+                                       # setting need_resched or sigpending
+                                       # between sampling and the iret
+       movl TI_flags(%ebp), %ecx
+       testw $_TIF_ALLWORK_MASK, %cx   # current->work
+       jne syscall_exit_work
+ restore_all:
+       testl $VM_MASK, EFLAGS(%esp)
+       jnz resume_vm86
+       movb EVENT_MASK(%esp), %al
+       notb %al                        # %al == ~saved_mask
++      XEN_LOCK_VCPU_INFO_SMP(%esi)
+       andb evtchn_upcall_mask(%esi),%al
+       andb $1,%al                     # %al == mask & ~saved_mask
+       jnz restore_all_enable_events   #     != 0 => reenable event delivery
++      XEN_UNLOCK_VCPU_INFO_SMP(%esi)
+       RESTORE_ALL
+ resume_vm86:
+       XEN_UNBLOCK_EVENTS(%esi)
+       RESTORE_REGS
+       movl %eax,(%esp)
+       movl $__HYPERVISOR_switch_vm86,%eax
+       int $0x82
+       ud2
+       # perform work that needs to be done immediately before resumption
+       ALIGN
+ work_pending:
+       testb $_TIF_NEED_RESCHED, %cl
+       jz work_notifysig
+ work_resched:
+       call schedule
+       XEN_BLOCK_EVENTS(%esi)          # make sure we don't miss an interrupt
+                                       # setting need_resched or sigpending
+                                       # between sampling and the iret
+       movl TI_flags(%ebp), %ecx
+       andl $_TIF_WORK_MASK, %ecx      # is there any work to be done other
+                                       # than syscall tracing?
+       jz restore_all
+       testb $_TIF_NEED_RESCHED, %cl
+       jnz work_resched
+ work_notifysig:                               # deal with pending signals and
+                                       # notify-resume requests
+       testl $VM_MASK, EFLAGS(%esp)
+       movl %esp, %eax
+       jne work_notifysig_v86          # returning to kernel-space or
+                                       # vm86-space
+       xorl %edx, %edx
+       call do_notify_resume
+       jmp restore_all
+       ALIGN
+ work_notifysig_v86:
+       pushl %ecx                      # save ti_flags for do_notify_resume
+       call save_v86_state             # %eax contains pt_regs pointer
+       popl %ecx
+       movl %eax, %esp
+       xorl %edx, %edx
+       call do_notify_resume
+       jmp restore_all
+       # perform syscall exit tracing
+       ALIGN
+ syscall_trace_entry:
+       movl $-ENOSYS,EAX(%esp)
+       movl %esp, %eax
+       xorl %edx,%edx
+       call do_syscall_trace
+       movl ORIG_EAX(%esp), %eax
+       cmpl $(nr_syscalls), %eax
+       jnae syscall_call
+       jmp syscall_exit
+       # perform syscall exit tracing
+       ALIGN
+ syscall_exit_work:
+       testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
+       jz work_pending
+       XEN_UNBLOCK_EVENTS(%esi)        # could let do_syscall_trace() call
+                                       # schedule() instead
+       movl %esp, %eax
+       movl $1, %edx
+       call do_syscall_trace
+       jmp resume_userspace
+       ALIGN
+ syscall_fault:
+       pushl %eax                      # save orig_eax
+       SAVE_ALL
+       GET_THREAD_INFO(%ebp)
+       movl $-EFAULT,EAX(%esp)
+       jmp resume_userspace
+       ALIGN
+ syscall_badsys:
+       movl $-ENOSYS,EAX(%esp)
+       jmp resume_userspace
+ #if 0 /* XEN */
+ /*
+  * Build the entry stubs and pointer table with
+  * some assembler magic.
+  */
+ .data
+ ENTRY(interrupt)
+ .text
+ vector=0
+ ENTRY(irq_entries_start)
+ .rept NR_IRQS
+       ALIGN
+ 1:    pushl $vector-256
+       jmp common_interrupt
+ .data
+       .long 1b
+ .text
+ vector=vector+1
+ .endr
+       ALIGN
+ common_interrupt:
+       SAVE_ALL
+       movl %esp,%eax
+       call do_IRQ
+       jmp ret_from_intr
+ #define BUILD_INTERRUPT(name, nr)     \
+ ENTRY(name)                           \
+       pushl $nr-256;                  \
+       SAVE_ALL                        \
+       movl %esp,%eax;                 \
+       call smp_/**/name;              \
+       jmp ret_from_intr;
+ /* The include is where all of the SMP etc. interrupts come from */
+ #include "entry_arch.h"
+ #endif /* XEN */
+ ENTRY(divide_error)
+       pushl $0                        # no error code
+       pushl $do_divide_error
+       ALIGN
+ error_code:
+       pushl %ds
+       pushl %eax
+       xorl %eax, %eax
+       pushl %ebp
+       pushl %edi
+       pushl %esi
+       pushl %edx
+       decl %eax                       # eax = -1
+       pushl %ecx
+       pushl %ebx
+       cld
+       movl %es, %ecx
+       movl ES(%esp), %edi             # get the function address
+       movl ORIG_EAX(%esp), %edx       # get the error code
+       movl %eax, ORIG_EAX(%esp)
+       movl %ecx, ES(%esp)
+       movl $(__USER_DS), %ecx
+       movl %ecx, %ds
+       movl %ecx, %es
+       movl %esp,%eax                  # pt_regs pointer
+       XEN_GET_VCPU_INFO(%esi)
+       XEN_SAVE_UPCALL_MASK(%esi,%bl,EVENT_MASK)
+       call *%edi
+       jmp ret_from_exception
+ # A note on the "critical region" in our callback handler.
+ # We want to avoid stacking callback handlers due to events occurring
+ # during handling of the last event. To do this, we keep events disabled
+ # until we've done all processing. HOWEVER, we must enable events before
+ # popping the stack frame (can't be done atomically) and so it would still
+ # be possible to get enough handler activations to overflow the stack.
+ # Although unlikely, bugs of that kind are hard to track down, so we'd
+ # like to avoid the possibility.
+ # So, on entry to the handler we detect whether we interrupted an
+ # existing activation in its critical region -- if so, we pop the current
+ # activation and restart the handler using the previous one.
+ ENTRY(hypervisor_callback)
+       pushl %eax
+       SAVE_ALL_NO_EVENTMASK
+       movl EIP(%esp),%eax
+       cmpl $scrit,%eax
+       jb   11f
+       cmpl $ecrit,%eax
+       jb   critical_region_fixup
+ 11:   XEN_GET_VCPU_INFO(%esi)
+       movb $0, EVENT_MASK(%esp)
+       push %esp
+       call evtchn_do_upcall
+       add  $4,%esp
+       jmp  ret_from_intr
+         ALIGN
+ restore_all_enable_events:  
+       XEN_UNBLOCK_EVENTS(%esi)
+ scrit:        /**** START OF CRITICAL REGION ****/
+       XEN_TEST_PENDING(%esi)
+       jnz  14f                        # process more events if necessary...
++      XEN_UNLOCK_VCPU_INFO_SMP(%esi)
+       RESTORE_ALL
+ 14:   XEN_BLOCK_EVENTS(%esi)
++      XEN_UNLOCK_VCPU_INFO_SMP(%esi)
+       jmp  11b
+ ecrit:  /**** END OF CRITICAL REGION ****/
+ # [How we do the fixup]. We want to merge the current stack frame with the
+ # just-interrupted frame. How we do this depends on where in the critical
+ # region the interrupted handler was executing, and so how many saved
+ # registers are in each frame. We do this quickly using the lookup table
+ # 'critical_fixup_table'. For each byte offset in the critical region, it
+ # provides the number of bytes which have already been popped from the
+ # interrupted stack frame. 
+ critical_region_fixup:
+       addl $critical_fixup_table-scrit,%eax
+       movzbl (%eax),%eax              # %eax contains num bytes popped
+       mov  %esp,%esi
+       add  %eax,%esi                  # %esi points at end of src region
+       mov  %esp,%edi
+       add  $0x34,%edi                 # %edi points at end of dst region
+       mov  %eax,%ecx
+       shr  $2,%ecx                    # convert words to bytes
+       je   16f                        # skip loop if nothing to copy
+ 15:   subl $4,%esi                    # pre-decrementing copy loop
+       subl $4,%edi
+       movl (%esi),%eax
+       movl %eax,(%edi)
+       loop 15b
+ 16:   movl %edi,%esp                  # final %edi is top of merged stack
+       jmp  11b
+ critical_fixup_table:
+       .byte 0x00,0x00,0x00            # testb $0xff,(%esi) = XEN_TEST_PENDING
+       .byte 0x00,0x00                 # jnz  14f
++      XEN_UNLOCK_VCPU_INFO_SMP_fixup
+       .byte 0x00                      # pop  %ebx
+       .byte 0x04                      # pop  %ecx
+       .byte 0x08                      # pop  %edx
+       .byte 0x0c                      # pop  %esi
+       .byte 0x10                      # pop  %edi
+       .byte 0x14                      # pop  %ebp
+       .byte 0x18                      # pop  %eax
+       .byte 0x1c                      # pop  %ds
+       .byte 0x20                      # pop  %es
+       .byte 0x24,0x24,0x24            # add  $4,%esp
+       .byte 0x28                      # iret
+       .byte 0x00,0x00,0x00,0x00       # movb $1,1(%esi)
++      XEN_UNLOCK_VCPU_INFO_SMP_fixup
+       .byte 0x00,0x00                 # jmp  11b
+ # Hypervisor uses this for application faults while it executes.
+ ENTRY(failsafe_callback)
+ 1:    popl %ds
+ 2:    popl %es
+ 3:    popl %fs
+ 4:    popl %gs
+       subl $4,%esp
+       SAVE_ALL
+       jmp  ret_from_exception
+ .section .fixup,"ax"; \
+ 6:    movl $0,(%esp); \
+       jmp 1b;         \
+ 7:    movl $0,(%esp); \
+       jmp 2b;         \
+ 8:    movl $0,(%esp); \
+       jmp 3b;         \
+ 9:    movl $0,(%esp); \
+       jmp 4b;         \
+ .previous;            \
+ .section __ex_table,"a";\
+       .align 4;       \
+       .long 1b,6b;    \
+       .long 2b,7b;    \
+       .long 3b,8b;    \
+       .long 4b,9b;    \
+ .previous
+ ENTRY(coprocessor_error)
+       pushl $0
+       pushl $do_coprocessor_error
+       jmp error_code
+ ENTRY(simd_coprocessor_error)
+       pushl $0
+       pushl $do_simd_coprocessor_error
+       jmp error_code
+ ENTRY(device_not_available)
+       pushl $-1                       # mark this as an int
+       SAVE_ALL
+       preempt_stop
+       call math_state_restore
+       jmp ret_from_exception
+ /*
+  * Debug traps and NMI can happen at the one SYSENTER instruction
+  * that sets up the real kernel stack. Check here, since we can't
+  * allow the wrong stack to be used.
+  *
+  * "TSS_sysenter_esp0+12" is because the NMI/debug handler will have
+  * already pushed 3 words if it hits on the sysenter instruction:
+  * eflags, cs and eip.
+  *
+  * We just load the right stack, and push the three (known) values
+  * by hand onto the new stack - while updating the return eip past
+  * the instruction that would have done it for sysenter.
+  */
+ #define FIX_STACK(offset, ok, label)          \
+       cmpw $__KERNEL_CS,4(%esp);              \
+       jne ok;                                 \
+ label:                                                \
+       movl TSS_sysenter_esp0+offset(%esp),%esp;       \
+       pushfl;                                 \
+       pushl $__KERNEL_CS;                     \
+       pushl $sysenter_past_esp
+ ENTRY(debug)
+       cmpl $sysenter_entry,(%esp)
+       jne debug_stack_correct
+       FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
+ debug_stack_correct:
+       pushl $-1                       # mark this as an int
+       SAVE_ALL
+       xorl %edx,%edx                  # error code 0
+       movl %esp,%eax                  # pt_regs pointer
+       call do_debug
+       testl %eax,%eax
+       jnz restore_all
+       jmp ret_from_exception
+ #if 0 /* XEN */
+ /*
+  * NMI is doubly nasty. It can happen _while_ we're handling
+  * a debug fault, and the debug fault hasn't yet been able to
+  * clear up the stack. So we first check whether we got  an
+  * NMI on the sysenter entry path, but after that we need to
+  * check whether we got an NMI on the debug path where the debug
+  * fault happened on the sysenter path.
+  */
+ ENTRY(nmi)
+       cmpl $sysenter_entry,(%esp)
+       je nmi_stack_fixup
+       pushl %eax
+       movl %esp,%eax
+       /* Do not access memory above the end of our stack page,
+        * it might not exist.
+        */
+       andl $(THREAD_SIZE-1),%eax
+       cmpl $(THREAD_SIZE-20),%eax
+       popl %eax
+       jae nmi_stack_correct
+       cmpl $sysenter_entry,12(%esp)
+       je nmi_debug_stack_check
+ nmi_stack_correct:
+       pushl %eax
+       SAVE_ALL
+       xorl %edx,%edx          # zero error code
+       movl %esp,%eax          # pt_regs pointer
+       call do_nmi
+       RESTORE_ALL
+ nmi_stack_fixup:
+       FIX_STACK(12,nmi_stack_correct, 1)
+       jmp nmi_stack_correct
+ nmi_debug_stack_check:
+       cmpw $__KERNEL_CS,16(%esp)
+       jne nmi_stack_correct
+       cmpl $debug - 1,(%esp)
+       jle nmi_stack_correct
+       cmpl $debug_esp_fix_insn,(%esp)
+       jle nmi_debug_stack_fixup
+ nmi_debug_stack_fixup:
+       FIX_STACK(24,nmi_stack_correct, 1)
+       jmp nmi_stack_correct
+ #endif /* XEN */
+ ENTRY(int3)
+       pushl $-1                       # mark this as an int
+       SAVE_ALL
+       xorl %edx,%edx          # zero error code
+       movl %esp,%eax          # pt_regs pointer
+       call do_int3
+       testl %eax,%eax
+       jnz restore_all
+       jmp ret_from_exception
+ ENTRY(overflow)
+       pushl $0
+       pushl $do_overflow
+       jmp error_code
+ ENTRY(bounds)
+       pushl $0
+       pushl $do_bounds
+       jmp error_code
+ ENTRY(invalid_op)
+       pushl $0
+       pushl $do_invalid_op
+       jmp error_code
+ ENTRY(coprocessor_segment_overrun)
+       pushl $0
+       pushl $do_coprocessor_segment_overrun
+       jmp error_code
+ ENTRY(invalid_TSS)
+       pushl $do_invalid_TSS
+       jmp error_code
+ ENTRY(segment_not_present)
+       pushl $do_segment_not_present
+       jmp error_code
+ ENTRY(stack_segment)
+       pushl $do_stack_segment
+       jmp error_code
+ ENTRY(general_protection)
+       pushl $do_general_protection
+       jmp error_code
+ ENTRY(alignment_check)
+       pushl $do_alignment_check
+       jmp error_code
+ # This handler is special, because it gets an extra value on its stack,
+ # which is the linear faulting address.
+ # fastcall register usage:  %eax = pt_regs, %edx = error code,
+ #                         %ecx = fault address
+ ENTRY(page_fault)
+       pushl %ds
+       pushl %eax
+       xorl %eax, %eax
+       pushl %ebp
+       pushl %edi
+       pushl %esi
+       pushl %edx
+       decl %eax                       /* eax = -1 */
+       pushl %ecx
+       pushl %ebx
+       cld
+       movl %es,%edi
+       movl ES(%esp), %ecx             /* get the faulting address */
+       movl ORIG_EAX(%esp), %edx       /* get the error code */
+       movl %eax, ORIG_EAX(%esp)
+       movl %edi, ES(%esp)
+       movl $(__KERNEL_DS),%eax
+       movl %eax, %ds
+       movl %eax, %es
+       movl %esp,%eax                  /* pt_regs pointer */
+       XEN_GET_VCPU_INFO(%esi)
+       XEN_SAVE_UPCALL_MASK(%esi,%bl,EVENT_MASK)
+       call do_page_fault
+       jmp ret_from_exception
+ #ifdef CONFIG_X86_MCE
+ ENTRY(machine_check)
+       pushl $0
+       pushl machine_check_vector
+       jmp error_code
+ #endif
+ ENTRY(fixup_4gb_segment)
+       pushl $do_fixup_4gb_segment
+       jmp error_code
+ .data
+ ENTRY(sys_call_table)
+       .long sys_restart_syscall       /* 0 - old "setup()" system call, used for restarting */
+       .long sys_exit
+       .long sys_fork
+       .long sys_read
+       .long sys_write
+       .long sys_open          /* 5 */
+       .long sys_close
+       .long sys_waitpid
+       .long sys_creat
+       .long sys_link
+       .long sys_unlink        /* 10 */
+       .long sys_execve
+       .long sys_chdir
+       .long sys_time
+       .long sys_mknod
+       .long sys_chmod         /* 15 */
+       .long sys_lchown16
+       .long sys_ni_syscall    /* old break syscall holder */
+       .long sys_stat
+       .long sys_lseek
+       .long sys_getpid        /* 20 */
+       .long sys_mount
+       .long sys_oldumount
+       .long sys_setuid16
+       .long sys_getuid16
+       .long sys_stime         /* 25 */
+       .long sys_ptrace
+       .long sys_alarm
+       .long sys_fstat
+       .long sys_pause
+       .long sys_utime         /* 30 */
+       .long sys_ni_syscall    /* old stty syscall holder */
+       .long sys_ni_syscall    /* old gtty syscall holder */
+       .long sys_access
+       .long sys_nice
+       .long sys_ni_syscall    /* 35 - old ftime syscall holder */
+       .long sys_sync
+       .long sys_kill
+       .long sys_rename
+       .long sys_mkdir
+       .long sys_rmdir         /* 40 */
+       .long sys_dup
+       .long sys_pipe
+       .long sys_times
+       .long sys_ni_syscall    /* old prof syscall holder */
+       .long sys_brk           /* 45 */
+       .long sys_setgid16
+       .long sys_getgid16
+       .long sys_signal
+       .long sys_geteuid16
+       .long sys_getegid16     /* 50 */
+       .long sys_acct
+       .long sys_umount        /* recycled never used phys() */
+       .long sys_ni_syscall    /* old lock syscall holder */
+       .long sys_ioctl
+       .long sys_fcntl         /* 55 */
+       .long sys_ni_syscall    /* old mpx syscall holder */
+       .long sys_setpgid
+       .long sys_ni_syscall    /* old ulimit syscall holder */
+       .long sys_olduname
+       .long sys_umask         /* 60 */
+       .long sys_chroot
+       .long sys_ustat
+       .long sys_dup2
+       .long sys_getppid
+       .long sys_getpgrp       /* 65 */
+       .long sys_setsid
+       .long sys_sigaction
+       .long sys_sgetmask
+       .long sys_ssetmask
+       .long sys_setreuid16    /* 70 */
+       .long sys_setregid16
+       .long sys_sigsuspend
+       .long sys_sigpending
+       .long sys_sethostname
+       .long sys_setrlimit     /* 75 */
+       .long sys_old_getrlimit
+       .long sys_getrusage
+       .long sys_gettimeofday
+       .long sys_settimeofday
+       .long sys_getgroups16   /* 80 */
+       .long sys_setgroups16
+       .long old_select
+       .long sys_symlink
+       .long sys_lstat
+       .long sys_readlink      /* 85 */
+       .long sys_uselib
+       .long sys_swapon
+       .long sys_reboot
+       .long old_readdir
+       .long old_mmap          /* 90 */
+       .long sys_munmap
+       .long sys_truncate
+       .long sys_ftruncate
+       .long sys_fchmod
+       .long sys_fchown16      /* 95 */
+       .long sys_getpriority
+       .long sys_setpriority
+       .long sys_ni_syscall    /* old profil syscall holder */
+       .long sys_statfs
+       .long sys_fstatfs       /* 100 */
+       .long sys_ioperm
+       .long sys_socketcall
+       .long sys_syslog
+       .long sys_setitimer
+       .long sys_getitimer     /* 105 */
+       .long sys_newstat
+       .long sys_newlstat
+       .long sys_newfstat
+       .long sys_uname
+       .long sys_iopl          /* 110 */
+       .long sys_vhangup
+       .long sys_ni_syscall    /* old "idle" system call */
+       .long sys_vm86old
+       .long sys_wait4
+       .long sys_swapoff       /* 115 */
+       .long sys_sysinfo
+       .long sys_ipc
+       .long sys_fsync
+       .long sys_sigreturn
+       .long sys_clone         /* 120 */
+       .long sys_setdomainname
+       .long sys_newuname
+       .long sys_modify_ldt
+       .long sys_adjtimex
+       .long sys_mprotect      /* 125 */
+       .long sys_sigprocmask
+       .long sys_ni_syscall    /* old "create_module" */ 
+       .long sys_init_module
+       .long sys_delete_module
+       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
+       .long sys_quotactl
+       .long sys_getpgid
+       .long sys_fchdir
+       .long sys_bdflush
+       .long sys_sysfs         /* 135 */
+       .long sys_personality
+       .long sys_ni_syscall    /* reserved for afs_syscall */
+       .long sys_setfsuid16
+       .long sys_setfsgid16
+       .long sys_llseek        /* 140 */
+       .long sys_getdents
+       .long sys_select
+       .long sys_flock
+       .long sys_msync
+       .long sys_readv         /* 145 */
+       .long sys_writev
+       .long sys_getsid
+       .long sys_fdatasync
+       .long sys_sysctl
+       .long sys_mlock         /* 150 */
+       .long sys_munlock
+       .long sys_mlockall
+       .long sys_munlockall
+       .long sys_sched_setparam
+       .long sys_sched_getparam   /* 155 */
+       .long sys_sched_setscheduler
+       .long sys_sched_getscheduler
+       .long sys_sched_yield
+       .long sys_sched_get_priority_max
+       .long sys_sched_get_priority_min  /* 160 */
+       .long sys_sched_rr_get_interval
+       .long sys_nanosleep
+       .long sys_mremap
+       .long sys_setresuid16
+       .long sys_getresuid16   /* 165 */
+       .long sys_vm86
+       .long sys_ni_syscall    /* Old sys_query_module */
+       .long sys_poll
+       .long sys_nfsservctl
+       .long sys_setresgid16   /* 170 */
+       .long sys_getresgid16
+       .long sys_prctl
+       .long sys_rt_sigreturn
+       .long sys_rt_sigaction
+       .long sys_rt_sigprocmask        /* 175 */
+       .long sys_rt_sigpending
+       .long sys_rt_sigtimedwait
+       .long sys_rt_sigqueueinfo
+       .long sys_rt_sigsuspend
+       .long sys_pread64       /* 180 */
+       .long sys_pwrite64
+       .long sys_chown16
+       .long sys_getcwd
+       .long sys_capget
+       .long sys_capset        /* 185 */
+       .long sys_sigaltstack
+       .long sys_sendfile
+       .long sys_ni_syscall    /* reserved for streams1 */
+       .long sys_ni_syscall    /* reserved for streams2 */
+       .long sys_vfork         /* 190 */
+       .long sys_getrlimit
+       .long sys_mmap2
+       .long sys_truncate64
+       .long sys_ftruncate64
+       .long sys_stat64        /* 195 */
+       .long sys_lstat64
+       .long sys_fstat64
+       .long sys_lchown
+       .long sys_getuid
+       .long sys_getgid        /* 200 */
+       .long sys_geteuid
+       .long sys_getegid
+       .long sys_setreuid
+       .long sys_setregid
+       .long sys_getgroups     /* 205 */
+       .long sys_setgroups
+       .long sys_fchown
+       .long sys_setresuid
+       .long sys_getresuid
+       .long sys_setresgid     /* 210 */
+       .long sys_getresgid
+       .long sys_chown
+       .long sys_setuid
+       .long sys_setgid
+       .long sys_setfsuid      /* 215 */
+       .long sys_setfsgid
+       .long sys_pivot_root
+       .long sys_mincore
+       .long sys_madvise
+       .long sys_getdents64    /* 220 */
+       .long sys_fcntl64
+       .long sys_ni_syscall    /* reserved for TUX */
+       .long sys_ni_syscall
+       .long sys_gettid
+       .long sys_readahead     /* 225 */
+       .long sys_setxattr
+       .long sys_lsetxattr
+       .long sys_fsetxattr
+       .long sys_getxattr
+       .long sys_lgetxattr     /* 230 */
+       .long sys_fgetxattr
+       .long sys_listxattr
+       .long sys_llistxattr
+       .long sys_flistxattr
+       .long sys_removexattr   /* 235 */
+       .long sys_lremovexattr
+       .long sys_fremovexattr
+       .long sys_tkill
+       .long sys_sendfile64
+       .long sys_futex         /* 240 */
+       .long sys_sched_setaffinity
+       .long sys_sched_getaffinity
+       .long sys_set_thread_area
+       .long sys_get_thread_area
+       .long sys_io_setup      /* 245 */
+       .long sys_io_destroy
+       .long sys_io_getevents
+       .long sys_io_submit
+       .long sys_io_cancel
+       .long sys_fadvise64     /* 250 */
+       .long sys_ni_syscall
+       .long sys_exit_group
+       .long sys_lookup_dcookie
+       .long sys_epoll_create
+       .long sys_epoll_ctl     /* 255 */
+       .long sys_epoll_wait
+       .long sys_remap_file_pages
+       .long sys_set_tid_address
+       .long sys_timer_create
+       .long sys_timer_settime         /* 260 */
+       .long sys_timer_gettime
+       .long sys_timer_getoverrun
+       .long sys_timer_delete
+       .long sys_clock_settime
+       .long sys_clock_gettime         /* 265 */
+       .long sys_clock_getres
+       .long sys_clock_nanosleep
+       .long sys_statfs64
+       .long sys_fstatfs64     
+       .long sys_tgkill        /* 270 */
+       .long sys_utimes
+       .long sys_fadvise64_64
+       .long sys_ni_syscall    /* sys_vserver */
+       .long sys_mbind
+       .long sys_get_mempolicy
+       .long sys_set_mempolicy
+       .long sys_mq_open
+       .long sys_mq_unlink
+       .long sys_mq_timedsend
+       .long sys_mq_timedreceive       /* 280 */
+       .long sys_mq_notify
+       .long sys_mq_getsetattr
+       .long sys_ni_syscall            /* reserved for kexec */
+       .long sys_waitid
+       .long sys_ni_syscall            /* 285 */ /* available */
+       .long sys_add_key
+       .long sys_request_key
+       .long sys_keyctl
+ syscall_table_size=(.-sys_call_table)
index 0000000000000000000000000000000000000000,b8ac0568da979242cea116bca8d801c08780d6ce..3d2d8947a4ca545efa5600ec1ec55658c76ee6a0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,167 +1,185 @@@
 -      /* Set up the stack pointer */
 -      lss stack_start,%esp
 -
+ #include <linux/config.h>
+ .section __xen_guest
+       .ascii  "GUEST_OS=linux,GUEST_VER=2.6,XEN_VER=2.0,VIRT_BASE=0xC0000000"
+       .ascii  ",LOADER=generic"
+       .ascii  ",PT_MODE_WRITABLE"
+       .byte   0
+ .text
+ #include <linux/threads.h>
+ #include <linux/linkage.h>
+ #include <asm/segment.h>
+ #include <asm/thread_info.h>
+ #include <asm/asm_offsets.h>
+ #include <asm-xen/xen-public/arch-x86_32.h>
+ /*
+  * References to members of the new_cpu_data structure.
+  */
+ #define X86           new_cpu_data+CPUINFO_x86
+ #define X86_VENDOR    new_cpu_data+CPUINFO_x86_vendor
+ #define X86_MODEL     new_cpu_data+CPUINFO_x86_model
+ #define X86_MASK      new_cpu_data+CPUINFO_x86_mask
+ #define X86_HARD_MATH new_cpu_data+CPUINFO_hard_math
+ #define X86_CPUID     new_cpu_data+CPUINFO_cpuid_level
+ #define X86_CAPABILITY        new_cpu_data+CPUINFO_x86_capability
+ #define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id
+ ENTRY(startup_32)
+       cld
+       /* Copy the necessary stuff from xen_start_info structure. */
+       mov  $xen_start_info_union,%edi
+       mov  $128,%ecx
+       rep movsl
++#ifdef CONFIG_SMP
++ENTRY(startup_32_smp)
++      cld
++#endif /* CONFIG_SMP */
++
++      /* Set up the stack pointer */
++      lss stack_start,%esp
++
+ checkCPUtype:
+       /* get vendor info */
+       xorl %eax,%eax                  # call CPUID with 0 -> return vendor ID
+       cpuid
+       movl %eax,X86_CPUID             # save CPUID level
+       movl %ebx,X86_VENDOR_ID         # lo 4 chars
+       movl %edx,X86_VENDOR_ID+4       # next 4 chars
+       movl %ecx,X86_VENDOR_ID+8       # last 4 chars
+       movl $1,%eax            # Use the CPUID instruction to get CPU type
+       cpuid
+       movb %al,%cl            # save reg for future use
+       andb $0x0f,%ah          # mask processor family
+       movb %ah,X86
+       andb $0xf0,%al          # mask model
+       shrb $4,%al
+       movb %al,X86_MODEL
+       andb $0x0f,%cl          # mask mask revision
+       movb %cl,X86_MASK
+       movl %edx,X86_CAPABILITY
++      incb ready
++
+       xorl %eax,%eax          # Clear FS/GS and LDT
+       movl %eax,%fs
+       movl %eax,%gs
+       cld             # gcc2 wants the direction flag cleared at all times
++#ifdef CONFIG_SMP
++      movb ready, %cl 
++      cmpb $1,%cl
++      je 1f                   # the first CPU calls start_kernel
++                              # all other CPUs call initialize_secondary
++      call initialize_secondary
++      jmp L6
++1:
++#endif /* CONFIG_SMP */
+       call start_kernel
+ L6:
+       jmp L6                  # main should never return here, but
+                               # just in case, we know what happens.
+ ENTRY(lgdt_finish)
+       movl $(__KERNEL_DS),%eax        # reload all the segment registers
+       movw %ax,%ss                    # after changing gdt.
+       movl $(__USER_DS),%eax          # DS/ES contains default USER segment
+       movw %ax,%ds
+       movw %ax,%es
+       popl %eax                       # reload CS by intersegment return
+       pushl $(__KERNEL_CS)
+       pushl %eax
+       lret
+ ENTRY(stack_start)
+       .long init_thread_union+THREAD_SIZE
+       .long __BOOT_DS
++ready:        .byte 0
++
+ .globl idt_descr
+ .globl cpu_gdt_descr
+       ALIGN
+       .word 0                         # 32-bit align idt_desc.address
+ idt_descr:
+       .word IDT_ENTRIES*8-1           # idt contains 256 entries
+       .long idt_table
+ # boot GDT descriptor (later on used by CPU#0):
+       .word 0                         # 32 bit align gdt_desc.address
+ cpu_gdt_descr:
+       .word GDT_SIZE
+       .long cpu_gdt_table
+       .fill NR_CPUS-1,8,0             # space for the other GDT descriptors
+ .org 0x1000
+ ENTRY(empty_zero_page)
+ .org 0x2000
+ ENTRY(swapper_pg_dir)
+ .org 0x3000
+ ENTRY(cpu_gdt_table)
+       .quad 0x0000000000000000        /* NULL descriptor */
+       .quad 0x0000000000000000        /* 0x0b reserved */
+       .quad 0x0000000000000000        /* 0x13 reserved */
+       .quad 0x0000000000000000        /* 0x1b reserved */
+       .quad 0x0000000000000000        /* 0x20 unused */
+       .quad 0x0000000000000000        /* 0x28 unused */
+       .quad 0x0000000000000000        /* 0x33 TLS entry 1 */
+       .quad 0x0000000000000000        /* 0x3b TLS entry 2 */
+       .quad 0x0000000000000000        /* 0x43 TLS entry 3 */
+       .quad 0x0000000000000000        /* 0x4b reserved */
+       .quad 0x0000000000000000        /* 0x53 reserved */
+       .quad 0x0000000000000000        /* 0x5b reserved */
+       .quad 0x00cfbb000000c3ff        /* 0x60 kernel 4GB code at 0x00000000 */
+       .quad 0x00cfb3000000c3ff        /* 0x68 kernel 4GB data at 0x00000000 */
+       .quad 0x00cffb000000c3ff        /* 0x73 user 4GB code at 0x00000000 */
+       .quad 0x00cff3000000c3ff        /* 0x7b user 4GB data at 0x00000000 */
+       .quad 0x0000000000000000        /* 0x80 TSS descriptor */
+       .quad 0x0000000000000000        /* 0x88 LDT descriptor */
+       /* Segments used for calling PnP BIOS */
+       .quad 0x0000000000000000        /* 0x90 32-bit code */
+       .quad 0x0000000000000000        /* 0x98 16-bit code */
+       .quad 0x0000000000000000        /* 0xa0 16-bit data */
+       .quad 0x0000000000000000        /* 0xa8 16-bit data */
+       .quad 0x0000000000000000        /* 0xb0 16-bit data */
+       /*
+        * The APM segments have byte granularity and their bases
+        * and limits are set at run time.
+        */
+       .quad 0x0000000000000000        /* 0xb8 APM CS    code */
+       .quad 0x0000000000000000        /* 0xc0 APM CS 16 code (16 bit) */
+       .quad 0x0000000000000000        /* 0xc8 APM DS    data */
+       .quad 0x0000000000000000        /* 0xd0 - unused */
+       .quad 0x0000000000000000        /* 0xd8 - unused */
+       .quad 0x0000000000000000        /* 0xe0 - unused */
+       .quad 0x0000000000000000        /* 0xe8 - unused */
+       .quad 0x0000000000000000        /* 0xf0 - unused */
+       .quad 0x0000000000000000        /* 0xf8 - GDT entry 31: double-fault TSS */
+       .fill GDT_ENTRIES-32,8,0
+ .org 0x4000
+ ENTRY(default_ldt)
+ .org 0x5000
+ /*
+  * Real beginning of normal "text" segment
+  */
+ ENTRY(stext)
+ ENTRY(_stext)
index 0000000000000000000000000000000000000000,a1f7bfee8898a950ac599798c72bcaf3319aa4e1..1076fb8f3b1b649aafc83bf556ad232faf1494a7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1542 +1,1543 @@@
 -multicall_entry_t multicall_list[8];
 -int nr_multicall_ents = 0;
+ /*
+  *  linux/arch/i386/kernel/setup.c
+  *
+  *  Copyright (C) 1995  Linus Torvalds
+  *
+  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+  *
+  *  Memory region support
+  *    David Parsons <orc@pell.chi.il.us>, July-August 1999
+  *
+  *  Added E820 sanitization routine (removes overlapping memory regions);
+  *  Brian Moyle <bmoyle@mvista.com>, February 2001
+  *
+  * Moved CPU detection code to cpu/${cpu}.c
+  *    Patrick Mochel <mochel@osdl.org>, March 2002
+  *
+  *  Provisions for empty E820 memory regions (reported by certain BIOSes).
+  *  Alex Achenbach <xela@slit.de>, December 2002.
+  *
+  */
+ /*
+  * This file handles the architecture-dependent parts of initialization
+  */
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+ #include <linux/tty.h>
+ #include <linux/ioport.h>
+ #include <linux/acpi.h>
+ #include <linux/apm_bios.h>
+ #include <linux/initrd.h>
+ #include <linux/bootmem.h>
+ #include <linux/seq_file.h>
+ #include <linux/console.h>
+ #include <linux/root_dev.h>
+ #include <linux/highmem.h>
+ #include <linux/module.h>
+ #include <linux/efi.h>
+ #include <linux/init.h>
+ #include <linux/edd.h>
++#include <linux/percpu.h>
+ #include <video/edid.h>
+ #include <asm/e820.h>
+ #include <asm/mpspec.h>
+ #include <asm/setup.h>
+ #include <asm/arch_hooks.h>
+ #include <asm/sections.h>
+ #include <asm/io_apic.h>
+ #include <asm/ist.h>
+ #include <asm/io.h>
+ #include <asm-xen/hypervisor.h>
+ #include "setup_arch_pre.h"
+ #include <bios_ebda.h>
+ /* Allows setting of maximum possible memory size  */
+ static unsigned long xen_override_max_pfn;
+ int disable_pse __initdata = 0;
+ /*
+  * Machine setup..
+  */
+ #ifdef CONFIG_EFI
+ int efi_enabled = 0;
+ EXPORT_SYMBOL(efi_enabled);
+ #endif
+ /* cpu data as detected by the assembly code in head.S */
+ struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 0, 1, 0, -1 };
+ /* common cpu data for all cpus */
+ struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 0, 1, 0, -1 };
+ unsigned long mmu_cr4_features;
+ EXPORT_SYMBOL_GPL(mmu_cr4_features);
+ #ifdef        CONFIG_ACPI_INTERPRETER
+       int acpi_disabled = 0;
+ #else
+       int acpi_disabled = 1;
+ #endif
+ EXPORT_SYMBOL(acpi_disabled);
+ #ifdef        CONFIG_ACPI_BOOT
+ int __initdata acpi_force = 0;
+ extern acpi_interrupt_flags   acpi_sci_flags;
+ #endif
+ int MCA_bus;
+ /* for MCA, but anyone else can use it if they want */
+ unsigned int machine_id;
+ unsigned int machine_submodel_id;
+ unsigned int BIOS_revision;
+ unsigned int mca_pentium_flag;
+ /* For PCI or other memory-mapped resources */
+ unsigned long pci_mem_start = 0x10000000;
+ /* user-defined highmem size */
+ static unsigned int highmem_pages = -1;
+ /*
+  * Setup options
+  */
+ struct drive_info_struct { char dummy[32]; } drive_info;
+ struct screen_info screen_info;
+ struct apm_info apm_info;
+ struct sys_desc_table_struct {
+       unsigned short length;
+       unsigned char table[0];
+ };
+ struct edid_info edid_info;
+ struct ist_info ist_info;
+ struct e820map e820;
+ unsigned char aux_device_present;
+ extern void early_cpu_init(void);
+ extern void dmi_scan_machine(void);
+ extern void generic_apic_probe(char *);
+ extern int root_mountflags;
+ unsigned long saved_videomode;
+ #define RAMDISK_IMAGE_START_MASK      0x07FF
+ #define RAMDISK_PROMPT_FLAG           0x8000
+ #define RAMDISK_LOAD_FLAG             0x4000  
+ static char command_line[COMMAND_LINE_SIZE];
+ unsigned char __initdata boot_params[PARAM_SIZE];
+ static struct resource data_resource = {
+       .name   = "Kernel data",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+ };
+ static struct resource code_resource = {
+       .name   = "Kernel code",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+ };
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ static struct resource system_rom_resource = {
+       .name   = "System ROM",
+       .start  = 0xf0000,
+       .end    = 0xfffff,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ };
+ static struct resource extension_rom_resource = {
+       .name   = "Extension ROM",
+       .start  = 0xe0000,
+       .end    = 0xeffff,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ };
+ static struct resource adapter_rom_resources[] = { {
+       .name   = "Adapter ROM",
+       .start  = 0xc8000,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ }, {
+       .name   = "Adapter ROM",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ }, {
+       .name   = "Adapter ROM",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ }, {
+       .name   = "Adapter ROM",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ }, {
+       .name   = "Adapter ROM",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ }, {
+       .name   = "Adapter ROM",
+       .start  = 0,
+       .end    = 0,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ } };
+ #define ADAPTER_ROM_RESOURCES \
+       (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
+ static struct resource video_rom_resource = {
+       .name   = "Video ROM",
+       .start  = 0xc0000,
+       .end    = 0xc7fff,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ };
+ #endif
+ static struct resource video_ram_resource = {
+       .name   = "Video RAM area",
+       .start  = 0xa0000,
+       .end    = 0xbffff,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+ };
+ static struct resource standard_io_resources[] = { {
+       .name   = "dma1",
+       .start  = 0x0000,
+       .end    = 0x001f,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+ }, {
+       .name   = "pic1",
+       .start  = 0x0020,
+       .end    = 0x0021,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+ }, {
+       .name   = "timer0",
+       .start  = 0x0040,
+       .end    = 0x0043,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+ }, {
+       .name   = "timer1",
+       .start  = 0x0050,
+       .end    = 0x0053,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+ }, {
+       .name   = "keyboard",
+       .start  = 0x0060,
+       .end    = 0x006f,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+ }, {
+       .name   = "dma page reg",
+       .start  = 0x0080,
+       .end    = 0x008f,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+ }, {
+       .name   = "pic2",
+       .start  = 0x00a0,
+       .end    = 0x00a1,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+ }, {
+       .name   = "dma2",
+       .start  = 0x00c0,
+       .end    = 0x00df,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+ }, {
+       .name   = "fpu",
+       .start  = 0x00f0,
+       .end    = 0x00ff,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_IO
+ } };
+ #define STANDARD_IO_RESOURCES \
+       (sizeof standard_io_resources / sizeof standard_io_resources[0])
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ #define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
+ static int __init romchecksum(unsigned char *rom, unsigned long length)
+ {
+       unsigned char *p, sum = 0;
+       for (p = rom; p < rom + length; p++)
+               sum += *p;
+       return sum == 0;
+ }
+ static void __init probe_roms(void)
+ {
+       unsigned long start, length, upper;
+       unsigned char *rom;
+       int           i;
+       /* video rom */
+       upper = adapter_rom_resources[0].start;
+       for (start = video_rom_resource.start; start < upper; start += 2048) {
+               rom = isa_bus_to_virt(start);
+               if (!romsignature(rom))
+                       continue;
+               video_rom_resource.start = start;
+               /* 0 < length <= 0x7f * 512, historically */
+               length = rom[2] * 512;
+               /* if checksum okay, trust length byte */
+               if (length && romchecksum(rom, length))
+                       video_rom_resource.end = start + length - 1;
+               request_resource(&iomem_resource, &video_rom_resource);
+               break;
+       }
+       start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
+       if (start < upper)
+               start = upper;
+       /* system rom */
+       request_resource(&iomem_resource, &system_rom_resource);
+       upper = system_rom_resource.start;
+       /* check for extension rom (ignore length byte!) */
+       rom = isa_bus_to_virt(extension_rom_resource.start);
+       if (romsignature(rom)) {
+               length = extension_rom_resource.end - extension_rom_resource.start + 1;
+               if (romchecksum(rom, length)) {
+                       request_resource(&iomem_resource, &extension_rom_resource);
+                       upper = extension_rom_resource.start;
+               }
+       }
+       /* check for adapter roms on 2k boundaries */
+       for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
+               rom = isa_bus_to_virt(start);
+               if (!romsignature(rom))
+                       continue;
+               /* 0 < length <= 0x7f * 512, historically */
+               length = rom[2] * 512;
+               /* but accept any length that fits if checksum okay */
+               if (!length || start + length > upper || !romchecksum(rom, length))
+                       continue;
+               adapter_rom_resources[i].start = start;
+               adapter_rom_resources[i].end = start + length - 1;
+               request_resource(&iomem_resource, &adapter_rom_resources[i]);
+               start = adapter_rom_resources[i++].end & ~2047UL;
+       }
+ }
+ #endif
+ /*
+  * Point at the empty zero page to start with. We map the real shared_info
+  * page as soon as fixmap is up and running.
+  */
+ shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+ EXPORT_SYMBOL(HYPERVISOR_shared_info);
+ unsigned long *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
+ EXPORT_SYMBOL(phys_to_machine_mapping);
++DEFINE_PER_CPU(multicall_entry_t, multicall_list[8]);
++DEFINE_PER_CPU(int, nr_multicall_ents);
+ /* Raw start-of-day parameters from the hypervisor. */
+ union xen_start_info_union xen_start_info_union;
+ static void __init limit_regions(unsigned long long size)
+ {
+       unsigned long long current_addr = 0;
+       int i;
+       if (efi_enabled) {
+               for (i = 0; i < memmap.nr_map; i++) {
+                       current_addr = memmap.map[i].phys_addr +
+                                      (memmap.map[i].num_pages << 12);
+                       if (memmap.map[i].type == EFI_CONVENTIONAL_MEMORY) {
+                               if (current_addr >= size) {
+                                       memmap.map[i].num_pages -=
+                                               (((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT);
+                                       memmap.nr_map = i + 1;
+                                       return;
+                               }
+                       }
+               }
+       }
+       for (i = 0; i < e820.nr_map; i++) {
+               if (e820.map[i].type == E820_RAM) {
+                       current_addr = e820.map[i].addr + e820.map[i].size;
+                       if (current_addr >= size) {
+                               e820.map[i].size -= current_addr-size;
+                               e820.nr_map = i + 1;
+                               return;
+                       }
+               }
+       }
+ }
+ static void __init add_memory_region(unsigned long long start,
+                                   unsigned long long size, int type)
+ {
+       int x;
+       if (!efi_enabled) {
+                       x = e820.nr_map;
+               if (x == E820MAX) {
+                   printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+                   return;
+               }
+               e820.map[x].addr = start;
+               e820.map[x].size = size;
+               e820.map[x].type = type;
+               e820.nr_map++;
+       }
+ } /* add_memory_region */
+ #define E820_DEBUG    1
+ static void __init print_memory_map(char *who)
+ {
+       int i;
+       for (i = 0; i < e820.nr_map; i++) {
+               printk(" %s: %016Lx - %016Lx ", who,
+                       e820.map[i].addr,
+                       e820.map[i].addr + e820.map[i].size);
+               switch (e820.map[i].type) {
+               case E820_RAM:  printk("(usable)\n");
+                               break;
+               case E820_RESERVED:
+                               printk("(reserved)\n");
+                               break;
+               case E820_ACPI:
+                               printk("(ACPI data)\n");
+                               break;
+               case E820_NVS:
+                               printk("(ACPI NVS)\n");
+                               break;
+               default:        printk("type %lu\n", e820.map[i].type);
+                               break;
+               }
+       }
+ }
+ #if 0
+ /*
+  * Sanitize the BIOS e820 map.
+  *
+  * Some e820 responses include overlapping entries.  The following 
+  * replaces the original e820 map with a new one, removing overlaps.
+  *
+  */
+ struct change_member {
+       struct e820entry *pbios; /* pointer to original bios entry */
+       unsigned long long addr; /* address for this change point */
+ };
+ struct change_member change_point_list[2*E820MAX] __initdata;
+ struct change_member *change_point[2*E820MAX] __initdata;
+ struct e820entry *overlap_list[E820MAX] __initdata;
+ struct e820entry new_bios[E820MAX] __initdata;
+ static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
+ {
+       struct change_member *change_tmp;
+       unsigned long current_type, last_type;
+       unsigned long long last_addr;
+       int chgidx, still_changing;
+       int overlap_entries;
+       int new_bios_entry;
+       int old_nr, new_nr, chg_nr;
+       int i;
+       /*
+               Visually we're performing the following (1,2,3,4 = memory types)...
+               Sample memory map (w/overlaps):
+                  ____22__________________
+                  ______________________4_
+                  ____1111________________
+                  _44_____________________
+                  11111111________________
+                  ____________________33__
+                  ___________44___________
+                  __________33333_________
+                  ______________22________
+                  ___________________2222_
+                  _________111111111______
+                  _____________________11_
+                  _________________4______
+               Sanitized equivalent (no overlap):
+                  1_______________________
+                  _44_____________________
+                  ___1____________________
+                  ____22__________________
+                  ______11________________
+                  _________1______________
+                  __________3_____________
+                  ___________44___________
+                  _____________33_________
+                  _______________2________
+                  ________________1_______
+                  _________________4______
+                  ___________________2____
+                  ____________________33__
+                  ______________________4_
+       */
+       /* if there's only one memory region, don't bother */
+       if (*pnr_map < 2)
+               return -1;
+       old_nr = *pnr_map;
+       /* bail out if we find any unreasonable addresses in bios map */
+       for (i=0; i<old_nr; i++)
+               if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
+                       return -1;
+       /* create pointers for initial change-point information (for sorting) */
+       for (i=0; i < 2*old_nr; i++)
+               change_point[i] = &change_point_list[i];
+       /* record all known change-points (starting and ending addresses),
+          omitting those that are for empty memory regions */
+       chgidx = 0;
+       for (i=0; i < old_nr; i++)      {
+               if (biosmap[i].size != 0) {
+                       change_point[chgidx]->addr = biosmap[i].addr;
+                       change_point[chgidx++]->pbios = &biosmap[i];
+                       change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
+                       change_point[chgidx++]->pbios = &biosmap[i];
+               }
+       }
+       chg_nr = chgidx;        /* true number of change-points */
+       /* sort change-point list by memory addresses (low -> high) */
+       still_changing = 1;
+       while (still_changing)  {
+               still_changing = 0;
+               for (i=1; i < chg_nr; i++)  {
+                       /* if <current_addr> > <last_addr>, swap */
+                       /* or, if current=<start_addr> & last=<end_addr>, swap */
+                       if ((change_point[i]->addr < change_point[i-1]->addr) ||
+                               ((change_point[i]->addr == change_point[i-1]->addr) &&
+                                (change_point[i]->addr == change_point[i]->pbios->addr) &&
+                                (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
+                          )
+                       {
+                               change_tmp = change_point[i];
+                               change_point[i] = change_point[i-1];
+                               change_point[i-1] = change_tmp;
+                               still_changing=1;
+                       }
+               }
+       }
+       /* create a new bios memory map, removing overlaps */
+       overlap_entries=0;       /* number of entries in the overlap table */
+       new_bios_entry=0;        /* index for creating new bios map entries */
+       last_type = 0;           /* start with undefined memory type */
+       last_addr = 0;           /* start with 0 as last starting address */
+       /* loop through change-points, determining affect on the new bios map */
+       for (chgidx=0; chgidx < chg_nr; chgidx++)
+       {
+               /* keep track of all overlapping bios entries */
+               if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
+               {
+                       /* add map entry to overlap list (> 1 entry implies an overlap) */
+                       overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
+               }
+               else
+               {
+                       /* remove entry from list (order independent, so swap with last) */
+                       for (i=0; i<overlap_entries; i++)
+                       {
+                               if (overlap_list[i] == change_point[chgidx]->pbios)
+                                       overlap_list[i] = overlap_list[overlap_entries-1];
+                       }
+                       overlap_entries--;
+               }
+               /* if there are overlapping entries, decide which "type" to use */
+               /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
+               current_type = 0;
+               for (i=0; i<overlap_entries; i++)
+                       if (overlap_list[i]->type > current_type)
+                               current_type = overlap_list[i]->type;
+               /* continue building up new bios map based on this information */
+               if (current_type != last_type)  {
+                       if (last_type != 0)      {
+                               new_bios[new_bios_entry].size =
+                                       change_point[chgidx]->addr - last_addr;
+                               /* move forward only if the new size was non-zero */
+                               if (new_bios[new_bios_entry].size != 0)
+                                       if (++new_bios_entry >= E820MAX)
+                                               break;  /* no more space left for new bios entries */
+                       }
+                       if (current_type != 0)  {
+                               new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
+                               new_bios[new_bios_entry].type = current_type;
+                               last_addr=change_point[chgidx]->addr;
+                       }
+                       last_type = current_type;
+               }
+       }
+       new_nr = new_bios_entry;   /* retain count for new bios entries */
+       /* copy new bios mapping into original location */
+       memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
+       *pnr_map = new_nr;
+       return 0;
+ }
+ /*
+  * Copy the BIOS e820 map into a safe place.
+  *
+  * Sanity-check it while we're at it..
+  *
+  * If we're lucky and live on a modern system, the setup code
+  * will have given us a memory map that we can use to properly
+  * set up memory.  If we aren't, we'll fake a memory map.
+  *
+  * We check to see that the memory map contains at least 2 elements
+  * before we'll use it, because the detection code in setup.S may
+  * not be perfect and most every PC known to man has two memory
+  * regions: one from 0 to 640k, and one from 1mb up.  (The IBM
+  * thinkpad 560x, for example, does not cooperate with the memory
+  * detection code.)
+  */
+ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
+ {
+       /* Only one memory region (or negative)? Ignore it */
+       if (nr_map < 2)
+               return -1;
+       do {
+               unsigned long long start = biosmap->addr;
+               unsigned long long size = biosmap->size;
+               unsigned long long end = start + size;
+               unsigned long type = biosmap->type;
+               /* Overflow in 64 bits? Ignore the memory map. */
+               if (start > end)
+                       return -1;
+               /*
+                * Some BIOSes claim RAM in the 640k - 1M region.
+                * Not right. Fix it up.
+                */
+               if (type == E820_RAM) {
+                       if (start < 0x100000ULL && end > 0xA0000ULL) {
+                               if (start < 0xA0000ULL)
+                                       add_memory_region(start, 0xA0000ULL-start, type);
+                               if (end <= 0x100000ULL)
+                                       continue;
+                               start = 0x100000ULL;
+                               size = end - start;
+                       }
+               }
+               add_memory_region(start, size, type);
+       } while (biosmap++,--nr_map);
+       return 0;
+ }
+ #endif
+ #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+ struct edd edd;
+ #ifdef CONFIG_EDD_MODULE
+ EXPORT_SYMBOL(edd);
+ #endif
+ /**
+  * copy_edd() - Copy the BIOS EDD information
+  *              from boot_params into a safe place.
+  *
+  */
+ static inline void copy_edd(void)
+ {
+      memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));
+      memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));
+      edd.mbr_signature_nr = EDD_MBR_SIG_NR;
+      edd.edd_info_nr = EDD_NR;
+ }
+ #else
+ static inline void copy_edd(void)
+ {
+ }
+ #endif
+ /*
+  * Do NOT EVER look at the BIOS memory size location.
+  * It does not work on many machines.
+  */
+ #define LOWMEMSIZE()  (0x9f000)
+ static void __init parse_cmdline_early (char ** cmdline_p)
+ {
+       char c = ' ', *to = command_line, *from = saved_command_line;
+       int len = 0;
+       int userdef = 0;
+       memcpy(saved_command_line, xen_start_info.cmd_line, MAX_CMDLINE);
+       /* Save unparsed command line copy for /proc/cmdline */
+       saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+       for (;;) {
+               /*
+                * "mem=nopentium" disables the 4MB page tables.
+                * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
+                * to <mem>, overriding the bios size.
+                * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+                * <start> to <start>+<mem>, overriding the bios size.
+                *
+                * HPA tells me bootloaders need to parse mem=, so no new
+                * option should be mem=  [also see Documentation/i386/boot.txt]
+                */
+               if (c == ' ' && !memcmp(from, "mem=", 4)) {
+                       if (to != command_line)
+                               to--;
+                       if (!memcmp(from+4, "nopentium", 9)) {
+                               from += 9+4;
+                               clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+                               disable_pse = 1;
+                       } else {
+                               /* If the user specifies memory size, we
+                                * limit the BIOS-provided memory map to
+                                * that size. exactmap can be used to specify
+                                * the exact map. mem=number can be used to
+                                * trim the existing memory map.
+                                */
+                               unsigned long long mem_size;
+  
+                               mem_size = memparse(from+4, &from);
+ #if 0
+                               limit_regions(mem_size);
+                               userdef=1;
+ #else
+                               xen_override_max_pfn =
+                                       (unsigned long)(mem_size>>PAGE_SHIFT);
+ #endif
+                       }
+               }
+               if (c == ' ' && !memcmp(from, "memmap=", 7)) {
+                       if (to != command_line)
+                               to--;
+                       if (!memcmp(from+7, "exactmap", 8)) {
+                               from += 8+7;
+                               e820.nr_map = 0;
+                               userdef = 1;
+                       } else {
+                               /* If the user specifies memory size, we
+                                * limit the BIOS-provided memory map to
+                                * that size. exactmap can be used to specify
+                                * the exact map. mem=number can be used to
+                                * trim the existing memory map.
+                                */
+                               unsigned long long start_at, mem_size;
+  
+                               mem_size = memparse(from+7, &from);
+                               if (*from == '@') {
+                                       start_at = memparse(from+1, &from);
+                                       add_memory_region(start_at, mem_size, E820_RAM);
+                               } else if (*from == '#') {
+                                       start_at = memparse(from+1, &from);
+                                       add_memory_region(start_at, mem_size, E820_ACPI);
+                               } else if (*from == '$') {
+                                       start_at = memparse(from+1, &from);
+                                       add_memory_region(start_at, mem_size, E820_RESERVED);
+                               } else {
+                                       limit_regions(mem_size);
+                                       userdef=1;
+                               }
+                       }
+               }
+ #ifdef  CONFIG_X86_SMP
+               /*
+                * If the BIOS enumerates physical processors before logical,
+                * maxcpus=N at enumeration-time can be used to disable HT.
+                */
+               else if (!memcmp(from, "maxcpus=", 8)) {
+                       extern unsigned int maxcpus;
+                       maxcpus = simple_strtoul(from + 8, NULL, 0);
+               }
+ #endif
+ #ifdef CONFIG_ACPI_BOOT
+               /* "acpi=off" disables both ACPI table parsing and interpreter */
+               else if (!memcmp(from, "acpi=off", 8)) {
+                       disable_acpi();
+               }
+               /* acpi=force to over-ride black-list */
+               else if (!memcmp(from, "acpi=force", 10)) {
+                       acpi_force = 1;
+                       acpi_ht = 1;
+                       acpi_disabled = 0;
+               }
+               /* acpi=strict disables out-of-spec workarounds */
+               else if (!memcmp(from, "acpi=strict", 11)) {
+                       acpi_strict = 1;
+               }
+               /* Limit ACPI just to boot-time to enable HT */
+               else if (!memcmp(from, "acpi=ht", 7)) {
+                       if (!acpi_force)
+                               disable_acpi();
+                       acpi_ht = 1;
+               }
+               
+               /* "pci=noacpi" disable ACPI IRQ routing and PCI scan */
+               else if (!memcmp(from, "pci=noacpi", 10)) {
+                       acpi_disable_pci();
+               }
+               /* "acpi=noirq" disables ACPI interrupt routing */
+               else if (!memcmp(from, "acpi=noirq", 10)) {
+                       acpi_noirq_set();
+               }
+               else if (!memcmp(from, "acpi_sci=edge", 13))
+                       acpi_sci_flags.trigger =  1;
+               else if (!memcmp(from, "acpi_sci=level", 14))
+                       acpi_sci_flags.trigger = 3;
+               else if (!memcmp(from, "acpi_sci=high", 13))
+                       acpi_sci_flags.polarity = 1;
+               else if (!memcmp(from, "acpi_sci=low", 12))
+                       acpi_sci_flags.polarity = 3;
+ #ifdef CONFIG_X86_IO_APIC
+               else if (!memcmp(from, "acpi_skip_timer_override", 24))
+                       acpi_skip_timer_override = 1;
+ #endif
+ #ifdef CONFIG_X86_LOCAL_APIC
+               /* disable IO-APIC */
+               else if (!memcmp(from, "noapic", 6))
+                       disable_ioapic_setup();
+ #endif /* CONFIG_X86_LOCAL_APIC */
+ #endif /* CONFIG_ACPI_BOOT */
+               /*
+                * highmem=size forces highmem to be exactly 'size' bytes.
+                * This works even on boxes that have no highmem otherwise.
+                * This also works to reduce highmem size on bigger boxes.
+                */
+               if (c == ' ' && !memcmp(from, "highmem=", 8))
+                       highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
+       
+               /*
+                * vmalloc=size forces the vmalloc area to be exactly 'size'
+                * bytes. This can be used to increase (or decrease) the
+                * vmalloc area - the default is 128m.
+                */
+               if (c == ' ' && !memcmp(from, "vmalloc=", 8))
+                       __VMALLOC_RESERVE = memparse(from+8, &from);
+               c = *(from++);
+               if (!c)
+                       break;
+               if (COMMAND_LINE_SIZE <= ++len)
+                       break;
+               *(to++) = c;
+       }
+       *to = '\0';
+       *cmdline_p = command_line;
+       if (userdef) {
+               printk(KERN_INFO "user-defined physical RAM map:\n");
+               print_memory_map("user");
+       }
+ }
+ #if 0 /* !XEN */
+ /*
+  * Callback for efi_memory_walk.
+  */
+ static int __init
+ efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
+ {
+       unsigned long *max_pfn = arg, pfn;
+       if (start < end) {
+               pfn = PFN_UP(end -1);
+               if (pfn > *max_pfn)
+                       *max_pfn = pfn;
+       }
+       return 0;
+ }
+ /*
+  * Find the highest page frame number we have available
+  */
+ void __init find_max_pfn(void)
+ {
+       int i;
+       max_pfn = 0;
+       if (efi_enabled) {
+               efi_memmap_walk(efi_find_max_pfn, &max_pfn);
+               return;
+       }
+       for (i = 0; i < e820.nr_map; i++) {
+               unsigned long start, end;
+               /* RAM? */
+               if (e820.map[i].type != E820_RAM)
+                       continue;
+               start = PFN_UP(e820.map[i].addr);
+               end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+               if (start >= end)
+                       continue;
+               if (end > max_pfn)
+                       max_pfn = end;
+       }
+ }
+ #else
+ /* We don't use the fake e820 because we need to respond to user override. */
+ void __init find_max_pfn(void)
+ {
+       if ( xen_override_max_pfn < xen_start_info.nr_pages )
+               xen_override_max_pfn = xen_start_info.nr_pages;
+       max_pfn = xen_override_max_pfn;
+ }
+ #endif /* XEN */
+ /*
+  * Determine low and high memory ranges:
+  */
+ unsigned long __init find_max_low_pfn(void)
+ {
+       unsigned long max_low_pfn;
+       max_low_pfn = max_pfn;
+       if (max_low_pfn > MAXMEM_PFN) {
+               if (highmem_pages == -1)
+                       highmem_pages = max_pfn - MAXMEM_PFN;
+               if (highmem_pages + MAXMEM_PFN < max_pfn)
+                       max_pfn = MAXMEM_PFN + highmem_pages;
+               if (highmem_pages + MAXMEM_PFN > max_pfn) {
+                       printk("only %luMB highmem pages available, ignoring highmem size of %uMB.\n", pages_to_mb(max_pfn - MAXMEM_PFN), pages_to_mb(highmem_pages));
+                       highmem_pages = 0;
+               }
+               max_low_pfn = MAXMEM_PFN;
+ #ifndef CONFIG_HIGHMEM
+               /* Maximum memory usable is what is directly addressable */
+               printk(KERN_WARNING "Warning only %ldMB will be used.\n",
+                                       MAXMEM>>20);
+               if (max_pfn > MAX_NONPAE_PFN)
+                       printk(KERN_WARNING "Use a PAE enabled kernel.\n");
+               else
+                       printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+               max_pfn = MAXMEM_PFN;
+ #else /* !CONFIG_HIGHMEM */
+ #ifndef CONFIG_X86_PAE
+               if (max_pfn > MAX_NONPAE_PFN) {
+                       max_pfn = MAX_NONPAE_PFN;
+                       printk(KERN_WARNING "Warning only 4GB will be used.\n");
+                       printk(KERN_WARNING "Use a PAE enabled kernel.\n");
+               }
+ #endif /* !CONFIG_X86_PAE */
+ #endif /* !CONFIG_HIGHMEM */
+       } else {
+               if (highmem_pages == -1)
+                       highmem_pages = 0;
+ #ifdef CONFIG_HIGHMEM
+               if (highmem_pages >= max_pfn) {
+                       printk(KERN_ERR "highmem size specified (%uMB) is bigger than pages available (%luMB)!.\n", pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
+                       highmem_pages = 0;
+               }
+               if (highmem_pages) {
+                       if (max_low_pfn-highmem_pages < 64*1024*1024/PAGE_SIZE){
+                               printk(KERN_ERR "highmem size %uMB results in smaller than 64MB lowmem, ignoring it.\n", pages_to_mb(highmem_pages));
+                               highmem_pages = 0;
+                       }
+                       max_low_pfn -= highmem_pages;
+               }
+ #else
+               if (highmem_pages)
+                       printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
+ #endif
+       }
+       return max_low_pfn;
+ }
+ #ifndef CONFIG_DISCONTIGMEM
+ /*
+  * Free all available memory for boot time allocation.  Used
+  * as a callback function by efi_memory_walk()
+  */
+ static int __init
+ free_available_memory(unsigned long start, unsigned long end, void *arg)
+ {
+       /* check max_low_pfn */
+       if (start >= ((max_low_pfn + 1) << PAGE_SHIFT))
+               return 0;
+       if (end >= ((max_low_pfn + 1) << PAGE_SHIFT))
+               end = (max_low_pfn + 1) << PAGE_SHIFT;
+       if (start < end)
+               free_bootmem(start, end - start);
+       return 0;
+ }
+ /*
+  * Register fully available low RAM pages with the bootmem allocator.
+  */
+ static void __init register_bootmem_low_pages(unsigned long max_low_pfn)
+ {
+       int i;
+       if (efi_enabled) {
+               efi_memmap_walk(free_available_memory, NULL);
+               return;
+       }
+       for (i = 0; i < e820.nr_map; i++) {
+               unsigned long curr_pfn, last_pfn, size;
+               /*
+                * Reserve usable low memory
+                */
+               if (e820.map[i].type != E820_RAM)
+                       continue;
+               /*
+                * We are rounding up the start address of usable memory:
+                */
+               curr_pfn = PFN_UP(e820.map[i].addr);
+               if (curr_pfn >= max_low_pfn)
+                       continue;
+               /*
+                * ... and at the end of the usable range downwards:
+                */
+               last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+               if (last_pfn > max_low_pfn)
+                       last_pfn = max_low_pfn;
+               /*
+                * .. finally, did all the rounding and playing
+                * around just make the area go away?
+                */
+               if (last_pfn <= curr_pfn)
+                       continue;
+               size = last_pfn - curr_pfn;
+               free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+       }
+ }
+ /*
+  * workaround for Dell systems that neglect to reserve EBDA
+  */
+ static void __init reserve_ebda_region(void)
+ {
+       unsigned int addr;
+       addr = get_bios_ebda();
+       if (addr)
+               reserve_bootmem(addr, PAGE_SIZE);       
+ }
+ static unsigned long __init setup_memory(void)
+ {
+       unsigned long bootmap_size, start_pfn, max_low_pfn;
+       /*
+        * partially used pages are not usable - thus
+        * we are rounding upwards:
+        */
+       start_pfn = PFN_UP(__pa(xen_start_info.pt_base)) + xen_start_info.nr_pt_frames;
+       find_max_pfn();
+       max_low_pfn = find_max_low_pfn();
+ #ifdef CONFIG_HIGHMEM
+       highstart_pfn = highend_pfn = max_pfn;
+       if (max_pfn > max_low_pfn) {
+               highstart_pfn = max_low_pfn;
+       }
+       printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+               pages_to_mb(highend_pfn - highstart_pfn));
+ #endif
+       printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
+                       pages_to_mb(max_low_pfn));
+       /*
+        * Initialize the boot-time allocator (with low memory only):
+        */
+       bootmap_size = init_bootmem(start_pfn, max_low_pfn);
+       register_bootmem_low_pages(max_low_pfn);
+       /*
+        * Reserve the bootmem bitmap itself as well. We do this in two
+        * steps (first step was init_bootmem()) because this catches
+        * the (very unlikely) case of us accidentally initializing the
+        * bootmem allocator with an invalid RAM area.
+        */
+       reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +
+                        bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
+       /* reserve EBDA region, it's a 4K region */
+       reserve_ebda_region();
+     /* could be an AMD 768MPX chipset. Reserve a page  before VGA to prevent
+        PCI prefetch into it (errata #56). Usually the page is reserved anyways,
+        unless you have no PS/2 mouse plugged in. */
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+           boot_cpu_data.x86 == 6)
+            reserve_bootmem(0xa0000 - 4096, 4096);
+ #ifdef CONFIG_SMP
+       /*
+        * But first pinch a few for the stack/trampoline stuff
+        * FIXME: Don't need the extra page at 4K, but need to fix
+        * trampoline before removing it. (see the GDT stuff)
+        */
+       reserve_bootmem(PAGE_SIZE, PAGE_SIZE);
+ #endif
+ #ifdef CONFIG_ACPI_SLEEP
+       /*
+        * Reserve low memory region for sleep support.
+        */
+       acpi_reserve_bootmem();
+ #endif
+ #ifdef CONFIG_X86_FIND_SMP_CONFIG
+       /*
+        * Find and reserve possible boot-time SMP configuration:
+        */
+       find_smp_config();
+ #endif
+ #ifdef CONFIG_BLK_DEV_INITRD
+       if (xen_start_info.mod_start) {
+               if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
+                       /*reserve_bootmem(INITRD_START, INITRD_SIZE);*/
+                       initrd_start = INITRD_START + PAGE_OFFSET;
+                       initrd_end = initrd_start+INITRD_SIZE;
+                       initrd_below_start_ok = 1;
+               }
+               else {
+                       printk(KERN_ERR "initrd extends beyond end of memory "
+                           "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+                           INITRD_START + INITRD_SIZE,
+                           max_low_pfn << PAGE_SHIFT);
+                       initrd_start = 0;
+               }
+       }
+ #endif
+       phys_to_machine_mapping = (unsigned long *)xen_start_info.mfn_list;
+       return max_low_pfn;
+ }
+ #else
+ extern unsigned long setup_memory(void);
+ #endif /* !CONFIG_DISCONTIGMEM */
+ /*
+  * Request address space for all standard RAM and ROM resources
+  * and also for regions reported as reserved by the e820.
+  */
+ static void __init
+ legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource)
+ {
+       int i;
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+       probe_roms();
+ #endif
+       for (i = 0; i < e820.nr_map; i++) {
+               struct resource *res;
+               if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
+                       continue;
+               res = alloc_bootmem_low(sizeof(struct resource));
+               switch (e820.map[i].type) {
+               case E820_RAM:  res->name = "System RAM"; break;
+               case E820_ACPI: res->name = "ACPI Tables"; break;
+               case E820_NVS:  res->name = "ACPI Non-volatile Storage"; break;
+               default:        res->name = "reserved";
+               }
+               res->start = e820.map[i].addr;
+               res->end = res->start + e820.map[i].size - 1;
+               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               request_resource(&iomem_resource, res);
+               if (e820.map[i].type == E820_RAM) {
+                       /*
+                        *  We don't know which RAM region contains kernel data,
+                        *  so we try it repeatedly and let the resource manager
+                        *  test it.
+                        */
+                       request_resource(res, code_resource);
+                       request_resource(res, data_resource);
+               }
+       }
+ }
+ /*
+  * Request address space for all standard resources
+  */
+ static void __init register_memory(unsigned long max_low_pfn)
+ {
+       unsigned long low_mem_size;
+       int           i;
+       if (efi_enabled)
+               efi_initialize_iomem_resources(&code_resource, &data_resource);
+       else
+               legacy_init_iomem_resources(&code_resource, &data_resource);
+       /* EFI systems may still have VGA */
+       request_resource(&iomem_resource, &video_ram_resource);
+       /* request I/O space for devices used on all i[345]86 PCs */
+       for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+               request_resource(&ioport_resource, &standard_io_resources[i]);
+       /* Tell the PCI layer not to allocate too close to the RAM area.. */
+       low_mem_size = ((max_low_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff;
+       if (low_mem_size > pci_mem_start)
+               pci_mem_start = low_mem_size;
+ }
+ /* Use inline assembly to define this because the nops are defined 
+    as inline assembly strings in the include files and we cannot 
+    get them easily into strings. */
+ asm("\t.data\nintelnops: " 
+     GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
+     GENERIC_NOP7 GENERIC_NOP8); 
+ asm("\t.data\nk8nops: " 
+     K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
+     K8_NOP7 K8_NOP8); 
+ asm("\t.data\nk7nops: " 
+     K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
+     K7_NOP7 K7_NOP8); 
+     
+ extern unsigned char intelnops[], k8nops[], k7nops[];
+ static unsigned char *intel_nops[ASM_NOP_MAX+1] = { 
+      NULL,
+      intelnops,
+      intelnops + 1,
+      intelnops + 1 + 2,
+      intelnops + 1 + 2 + 3,
+      intelnops + 1 + 2 + 3 + 4,
+      intelnops + 1 + 2 + 3 + 4 + 5,
+      intelnops + 1 + 2 + 3 + 4 + 5 + 6,
+      intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+ }; 
+ static unsigned char *k8_nops[ASM_NOP_MAX+1] = { 
+      NULL,
+      k8nops,
+      k8nops + 1,
+      k8nops + 1 + 2,
+      k8nops + 1 + 2 + 3,
+      k8nops + 1 + 2 + 3 + 4,
+      k8nops + 1 + 2 + 3 + 4 + 5,
+      k8nops + 1 + 2 + 3 + 4 + 5 + 6,
+      k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+ }; 
+ static unsigned char *k7_nops[ASM_NOP_MAX+1] = { 
+      NULL,
+      k7nops,
+      k7nops + 1,
+      k7nops + 1 + 2,
+      k7nops + 1 + 2 + 3,
+      k7nops + 1 + 2 + 3 + 4,
+      k7nops + 1 + 2 + 3 + 4 + 5,
+      k7nops + 1 + 2 + 3 + 4 + 5 + 6,
+      k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+ }; 
+ static struct nop { 
+      int cpuid; 
+      unsigned char **noptable; 
+ } noptypes[] = { 
+      { X86_FEATURE_K8, k8_nops }, 
+      { X86_FEATURE_K7, k7_nops }, 
+      { -1, NULL }
+ }; 
+ /* Replace instructions with better alternatives for this CPU type.
+    This runs before SMP is initialized to avoid SMP problems with
+    self modifying code. This implies that assymetric systems where
+    APs have less capabilities than the boot processor are not handled. 
+    In this case boot with "noreplacement". */ 
+ void apply_alternatives(void *start, void *end) 
+ { 
+       struct alt_instr *a; 
+       int diff, i, k;
+         unsigned char **noptable = intel_nops; 
+       for (i = 0; noptypes[i].cpuid >= 0; i++) { 
+               if (boot_cpu_has(noptypes[i].cpuid)) { 
+                       noptable = noptypes[i].noptable;
+                       break;
+               }
+       } 
+       for (a = start; (void *)a < end; a++) { 
+               if (!boot_cpu_has(a->cpuid))
+                       continue;
+               BUG_ON(a->replacementlen > a->instrlen); 
+               memcpy(a->instr, a->replacement, a->replacementlen); 
+               diff = a->instrlen - a->replacementlen; 
+               /* Pad the rest with nops */
+               for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
+                       k = diff;
+                       if (k > ASM_NOP_MAX)
+                               k = ASM_NOP_MAX;
+                       memcpy(a->instr + i, noptable[k], k); 
+               } 
+       }
+ } 
+ static int no_replacement __initdata = 0; 
+  
+ void __init alternative_instructions(void)
+ {
+       extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
+       if (no_replacement) 
+               return;
+       apply_alternatives(__alt_instructions, __alt_instructions_end);
+ }
+ static int __init noreplacement_setup(char *s)
+ { 
+      no_replacement = 1; 
+      return 0; 
+ } 
+ __setup("noreplacement", noreplacement_setup); 
+ static char * __init machine_specific_memory_setup(void);
+ /*
+  * Determine if we were loaded by an EFI loader.  If so, then we have also been
+  * passed the efi memmap, systab, etc., so we should use these data structures
+  * for initialization.  Note, the efi init code path is determined by the
+  * global efi_enabled. This allows the same kernel image to be used on existing
+  * systems (with a traditional BIOS) as well as on EFI systems.
+  */
+ void __init setup_arch(char **cmdline_p)
+ {
+         int i,j;
+         unsigned long max_low_pfn;
+       /* Force a quick death if the kernel panics. */
+       extern int panic_timeout;
+       if ( panic_timeout == 0 )
+               panic_timeout = 1;
+       HYPERVISOR_vm_assist(VMASST_CMD_enable,
+                            VMASST_TYPE_4gb_segments);
+       memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
+       early_cpu_init();
+       /*
+        * FIXME: This isn't an official loader_type right
+        * now but does currently work with elilo.
+        * If we were configured as an EFI kernel, check to make
+        * sure that we were loaded correctly from elilo and that
+        * the system table is valid.  If not, then initialize normally.
+        */
+ #ifdef CONFIG_EFI
+       if ((LOADER_TYPE == 0x50) && EFI_SYSTAB)
+               efi_enabled = 1;
+ #endif
+       ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); /*old_decode_dev(ORIG_ROOT_DEV);*/
+       drive_info = DRIVE_INFO;
+       screen_info = SCREEN_INFO;
+       edid_info = EDID_INFO;
+       apm_info.bios = APM_BIOS_INFO;
+       ist_info = IST_INFO;
+       saved_videomode = VIDEO_MODE;
+       if( SYS_DESC_TABLE.length != 0 ) {
+               MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
+               machine_id = SYS_DESC_TABLE.table[0];
+               machine_submodel_id = SYS_DESC_TABLE.table[1];
+               BIOS_revision = SYS_DESC_TABLE.table[2];
+       }
+       aux_device_present = AUX_DEVICE_INFO;
+ #ifdef CONFIG_XEN_PHYSDEV_ACCESS
+       /* This is drawn from a dump from vgacon:startup in standard Linux. */
+       screen_info.orig_video_mode = 3; 
+       screen_info.orig_video_isVGA = 1;
+       screen_info.orig_video_lines = 25;
+       screen_info.orig_video_cols = 80;
+       screen_info.orig_video_ega_bx = 3;
+       screen_info.orig_video_points = 16;
+ #endif
+ #ifdef CONFIG_BLK_DEV_RAM
+       rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+       rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+       rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+ #endif
+       ARCH_SETUP
+       if (efi_enabled)
+               efi_init();
+       else {
+               printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+               print_memory_map(machine_specific_memory_setup());
+       }
+       copy_edd();
+       if (!MOUNT_ROOT_RDONLY)
+               root_mountflags &= ~MS_RDONLY;
+       init_mm.start_code = (unsigned long) _text;
+       init_mm.end_code = (unsigned long) _etext;
+       init_mm.end_data = (unsigned long) _edata;
+       init_mm.brk = (PFN_UP(__pa(xen_start_info.pt_base)) + xen_start_info.nr_pt_frames) << PAGE_SHIFT;
+       /* XEN: This is nonsense: kernel may not even be contiguous in RAM. */
+       /*code_resource.start = virt_to_phys(_text);*/
+       /*code_resource.end = virt_to_phys(_etext)-1;*/
+       /*data_resource.start = virt_to_phys(_etext);*/
+       /*data_resource.end = virt_to_phys(_edata)-1;*/
+       parse_cmdline_early(cmdline_p);
+       max_low_pfn = setup_memory();
+       /*
+        * NOTE: before this point _nobody_ is allowed to allocate
+        * any memory using the bootmem allocator.  Although the
+        * alloctor is now initialised only the first 8Mb of the kernel
+        * virtual address space has been mapped.  All allocations before
+        * paging_init() has completed must use the alloc_bootmem_low_pages()
+        * variant (which allocates DMA'able memory) and care must be taken
+        * not to exceed the 8Mb limit.
+        */
+ #ifdef CONFIG_SMP
+       smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
+ #endif
+       paging_init();
+       /* Make sure we have a large enough P->M table. */
+       if (max_pfn > xen_start_info.nr_pages) {
+               phys_to_machine_mapping = alloc_bootmem_low_pages(
+                       max_pfn * sizeof(unsigned long));
+               memset(phys_to_machine_mapping, ~0,
+                       max_pfn * sizeof(unsigned long));
+               memcpy(phys_to_machine_mapping,
+                       (unsigned long *)xen_start_info.mfn_list,
+                       xen_start_info.nr_pages * sizeof(unsigned long));
+               free_bootmem(
+                       __pa(xen_start_info.mfn_list), 
+                       PFN_PHYS(PFN_UP(xen_start_info.nr_pages *
+                       sizeof(unsigned long))));
+       }
+       pfn_to_mfn_frame_list = alloc_bootmem_low_pages(PAGE_SIZE);
+       for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
+       {       
+            pfn_to_mfn_frame_list[j] = 
+                 virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
+       }
+       HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
+            virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
+       /*
+        * NOTE: at this point the bootmem allocator is fully available.
+        */
+ #ifdef CONFIG_EARLY_PRINTK
+       {
+               char *s = strstr(*cmdline_p, "earlyprintk=");
+               if (s) {
+                       extern void setup_early_printk(char *);
+                       setup_early_printk(s);
+                       printk("early console enabled\n");
+               }
+       }
+ #endif
+       dmi_scan_machine();
+ #ifdef CONFIG_X86_GENERICARCH
+       generic_apic_probe(*cmdline_p);
+ #endif        
+       if (efi_enabled)
+               efi_map_memmap();
+       /*
+        * Parse the ACPI tables for possible boot-time SMP configuration.
+        */
+       acpi_boot_init();
+ #ifdef CONFIG_X86_LOCAL_APIC
+       if (smp_found_config)
+               get_smp_config();
+ #endif
+       register_memory(max_low_pfn);
+       /* If we are a privileged guest OS then we should request IO privs. */
+       if (xen_start_info.flags & SIF_PRIVILEGED) {
+               dom0_op_t op;
+               op.cmd           = DOM0_IOPL;
+               op.u.iopl.domain = DOMID_SELF;
+               op.u.iopl.iopl   = 1;
+               if (HYPERVISOR_dom0_op(&op) != 0)
+                       panic("Unable to obtain IOPL, despite SIF_PRIVILEGED");
+               current->thread.io_pl = 1;
+       }
+       if (xen_start_info.flags & SIF_INITDOMAIN) {
+               if (!(xen_start_info.flags & SIF_PRIVILEGED))
+                       panic("Xen granted us console access "
+                             "but not privileged status");
+ #ifdef CONFIG_VT
+ #if defined(CONFIG_VGA_CONSOLE)
+               if (!efi_enabled ||
+                   (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+                       conswitchp = &vga_con;
+ #elif defined(CONFIG_DUMMY_CONSOLE)
+               conswitchp = &dummy_con;
+ #endif
+ #endif
+       } else {
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+               extern const struct consw xennull_con;
+               extern int console_use_vt;
+ #if defined(CONFIG_VGA_CONSOLE)
+               /* disable VGA driver */
+               ORIG_VIDEO_ISVGA = VIDEO_TYPE_VLFB;
+ #endif
+               conswitchp = &xennull_con;
+               console_use_vt = 0;
+ #endif
+       }
+ }
+ #include "setup_arch_post.h"
+ /*
+  * Local Variables:
+  * mode:c
+  * c-file-style:"k&r"
+  * c-basic-offset:8
+  * End:
+  */
index 0000000000000000000000000000000000000000,712e0948f1d1484dace9dd54b0f62c6dad2ecdc4..41046b7bc1085113cd590c9688863496d8b228f2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,733 +1,811 @@@
 -extern u64 processed_system_time;
+ /*
+  *  linux/arch/i386/kernel/time.c
+  *
+  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+  *
+  * This file contains the PC-specific time handling details:
+  * reading the RTC at bootup, etc..
+  * 1994-07-02    Alan Modra
+  *    fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
+  * 1995-03-26    Markus Kuhn
+  *      fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
+  *      precision CMOS clock update
+  * 1996-05-03    Ingo Molnar
+  *      fixed time warps in do_[slow|fast]_gettimeoffset()
+  * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
+  *            "A Kernel Model for Precision Timekeeping" by Dave Mills
+  * 1998-09-05    (Various)
+  *    More robust do_fast_gettimeoffset() algorithm implemented
+  *    (works with APM, Cyrix 6x86MX and Centaur C6),
+  *    monotonic gettimeofday() with fast_get_timeoffset(),
+  *    drift-proof precision TSC calibration on boot
+  *    (C. Scott Ananian <cananian@alumni.princeton.edu>, Andrew D.
+  *    Balsa <andrebalsa@altern.org>, Philip Gladstone <philip@raptor.com>;
+  *    ported from 2.0.35 Jumbo-9 by Michael Krause <m.krause@tu-harburg.de>).
+  * 1998-12-16    Andrea Arcangeli
+  *    Fixed Jumbo-9 code in 2.1.131: do_gettimeofday was missing 1 jiffy
+  *    because was not accounting lost_ticks.
+  * 1998-12-24 Copyright (C) 1998  Andrea Arcangeli
+  *    Fixed a xtime SMP race (we need the xtime_lock rw spinlock to
+  *    serialize accesses to xtime/lost_ticks).
+  */
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/param.h>
+ #include <linux/string.h>
+ #include <linux/mm.h>
+ #include <linux/interrupt.h>
+ #include <linux/time.h>
+ #include <linux/delay.h>
+ #include <linux/init.h>
+ #include <linux/smp.h>
+ #include <linux/module.h>
+ #include <linux/sysdev.h>
+ #include <linux/bcd.h>
+ #include <linux/efi.h>
+ #include <linux/sysctl.h>
++#include <linux/percpu.h>
+ #include <asm/io.h>
+ #include <asm/smp.h>
+ #include <asm/irq.h>
+ #include <asm/msr.h>
+ #include <asm/delay.h>
+ #include <asm/mpspec.h>
+ #include <asm/uaccess.h>
+ #include <asm/processor.h>
+ #include <asm/timer.h>
+ #include "mach_time.h"
+ #include <linux/timex.h>
+ #include <linux/config.h>
+ #include <asm/hpet.h>
+ #include <asm/arch_hooks.h>
+ #include "io_ports.h"
+ extern spinlock_t i8259A_lock;
+ int pit_latch_buggy;              /* extern */
+ u64 jiffies_64 = INITIAL_JIFFIES;
+ EXPORT_SYMBOL(jiffies_64);
+ unsigned long cpu_khz;        /* Detected as we calibrate the TSC */
+ extern unsigned long wall_jiffies;
+ spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+ spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
+ EXPORT_SYMBOL(i8253_lock);
+ extern struct init_timer_opts __initdata timer_tsc_init;
+ extern struct timer_opts timer_tsc;
+ struct timer_opts *cur_timer = &timer_tsc;
+ /* These are peridically updated in shared_info, and then copied here. */
+ u32 shadow_tsc_stamp;
+ u64 shadow_system_time;
+ static u32 shadow_time_version;
+ static struct timeval shadow_tv;
 -#ifndef CONFIG_SMP
+ /*
+  * We use this to ensure that gettimeofday() is monotonically increasing. We
+  * only break this guarantee if the wall clock jumps backwards "a long way".
+  */
+ static struct timeval last_seen_tv = {0,0};
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ /* Periodically propagate synchronised time base to the RTC and to Xen. */
+ static long last_rtc_update, last_update_to_xen;
+ #endif
+ /* Periodically take synchronised time base from Xen, if we need it. */
+ static long last_update_from_xen;   /* UTC seconds when last read Xen clock. */
+ /* Keep track of last time we did processing/updating of jiffies and xtime. */
+ u64 processed_system_time;   /* System time (ns) at last processing. */
++DEFINE_PER_CPU(u64, processed_system_time);
+ #define NS_PER_TICK (1000000000ULL/HZ)
+ #define HANDLE_USEC_UNDERFLOW(_tv) do {               \
+       while ((_tv).tv_usec < 0) {             \
+               (_tv).tv_usec += USEC_PER_SEC;  \
+               (_tv).tv_sec--;                 \
+       }                                       \
+ } while (0)
+ #define HANDLE_USEC_OVERFLOW(_tv) do {                \
+       while ((_tv).tv_usec >= USEC_PER_SEC) { \
+               (_tv).tv_usec -= USEC_PER_SEC;  \
+               (_tv).tv_sec++;                 \
+       }                                       \
+ } while (0)
+ static inline void __normalize_time(time_t *sec, s64 *nsec)
+ {
+       while (*nsec >= NSEC_PER_SEC) {
+               (*nsec) -= NSEC_PER_SEC;
+               (*sec)++;
+       }
+       while (*nsec < 0) {
+               (*nsec) += NSEC_PER_SEC;
+               (*sec)--;
+       }
+ }
+ /* Does this guest OS track Xen time, or set its wall clock independently? */
+ static int independent_wallclock = 0;
+ static int __init __independent_wallclock(char *str)
+ {
+       independent_wallclock = 1;
+       return 1;
+ }
+ __setup("independent_wallclock", __independent_wallclock);
+ #define INDEPENDENT_WALLCLOCK() \
+     (independent_wallclock || (xen_start_info.flags & SIF_INITDOMAIN))
+ /*
+  * Reads a consistent set of time-base values from Xen, into a shadow data
+  * area. Must be called with the xtime_lock held for writing.
+  */
+ static void __get_time_values_from_xen(void)
+ {
+       shared_info_t *s = HYPERVISOR_shared_info;
+       do {
+               shadow_time_version = s->time_version2;
+               rmb();
+               shadow_tv.tv_sec    = s->wc_sec;
+               shadow_tv.tv_usec   = s->wc_usec;
+               shadow_tsc_stamp    = (u32)s->tsc_timestamp;
+               shadow_system_time  = s->system_time;
+               rmb();
+       }
+       while (shadow_time_version != s->time_version1);
+       cur_timer->mark_offset();
+ }
+ #define TIME_VALUES_UP_TO_DATE \
+  ({ rmb(); (shadow_time_version == HYPERVISOR_shared_info->time_version2); })
+ /*
+  * This version of gettimeofday has microsecond resolution
+  * and better than microsecond precision on fast x86 machines with TSC.
+  */
+ void do_gettimeofday(struct timeval *tv)
+ {
+       unsigned long seq;
+       unsigned long usec, sec;
+       unsigned long max_ntp_tick;
+       unsigned long flags;
+       s64 nsec;
+       do {
+               unsigned long lost;
+               seq = read_seqbegin(&xtime_lock);
+               usec = cur_timer->get_offset();
+               lost = jiffies - wall_jiffies;
+               /*
+                * If time_adjust is negative then NTP is slowing the clock
+                * so make sure not to go into next possible interval.
+                * Better to lose some accuracy than have time go backwards..
+                */
+               if (unlikely(time_adjust < 0)) {
+                       max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
+                       usec = min(usec, max_ntp_tick);
+                       if (lost)
+                               usec += lost * max_ntp_tick;
+               }
+               else if (unlikely(lost))
+                       usec += lost * (USEC_PER_SEC / HZ);
+               sec = xtime.tv_sec;
+               usec += (xtime.tv_nsec / NSEC_PER_USEC);
+               nsec = shadow_system_time - processed_system_time;
+               __normalize_time(&sec, &nsec);
+               usec += (long)nsec / NSEC_PER_USEC;
+               if (unlikely(!TIME_VALUES_UP_TO_DATE)) {
+                       /*
+                        * We may have blocked for a long time,
+                        * rendering our calculations invalid
+                        * (e.g. the time delta may have
+                        * overflowed). Detect that and recalculate
+                        * with fresh values.
+                        */
+                       write_seqlock_irqsave(&xtime_lock, flags);
+                       __get_time_values_from_xen();
+                       write_sequnlock_irqrestore(&xtime_lock, flags);
+                       continue;
+               }
+       } while (read_seqretry(&xtime_lock, seq));
+       while (usec >= USEC_PER_SEC) {
+               usec -= USEC_PER_SEC;
+               sec++;
+       }
+       /* Ensure that time-of-day is monotonically increasing. */
+       if ((sec < last_seen_tv.tv_sec) ||
+           ((sec == last_seen_tv.tv_sec) && (usec < last_seen_tv.tv_usec))) {
+               sec = last_seen_tv.tv_sec;
+               usec = last_seen_tv.tv_usec;
+       } else {
+               last_seen_tv.tv_sec = sec;
+               last_seen_tv.tv_usec = usec;
+       }
+       tv->tv_sec = sec;
+       tv->tv_usec = usec;
+ }
+ EXPORT_SYMBOL(do_gettimeofday);
+ int do_settimeofday(struct timespec *tv)
+ {
+       time_t wtm_sec, sec = tv->tv_sec;
+       long wtm_nsec;
+       s64 nsec;
+       struct timespec xentime;
+       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+               return -EINVAL;
+       if (!INDEPENDENT_WALLCLOCK())
+               return 0; /* Silent failure? */
+       write_seqlock_irq(&xtime_lock);
+       /*
+        * Ensure we don't get blocked for a long time so that our time delta
+        * overflows. If that were to happen then our shadow time values would
+        * be stale, so we can retry with fresh ones.
+        */
+  again:
+       nsec = (s64)tv->tv_nsec -
+           ((s64)cur_timer->get_offset() * (s64)NSEC_PER_USEC);
+       if (unlikely(!TIME_VALUES_UP_TO_DATE)) {
+               __get_time_values_from_xen();
+               goto again;
+       }
+       __normalize_time(&sec, &nsec);
+       set_normalized_timespec(&xentime, sec, nsec);
+       /*
+        * This is revolting. We need to set "xtime" correctly. However, the
+        * value in this location is the value at the most recent update of
+        * wall time.  Discover what correction gettimeofday() would have
+        * made, and then undo it!
+        */
+       nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
+       nsec -= (shadow_system_time - processed_system_time);
+       __normalize_time(&sec, &nsec);
+       wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+       set_normalized_timespec(&xtime, sec, nsec);
+       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+       time_adjust = 0;                /* stop active adjtime() */
+       time_status |= STA_UNSYNC;
+       time_maxerror = NTP_PHASE_LIMIT;
+       time_esterror = NTP_PHASE_LIMIT;
+       /* Reset all our running time counts. They make no sense now. */
+       last_seen_tv.tv_sec = 0;
+       last_update_from_xen = 0;
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+       if (xen_start_info.flags & SIF_INITDOMAIN) {
+               dom0_op_t op;
+               last_rtc_update = last_update_to_xen = 0;
+               op.cmd = DOM0_SETTIME;
+               op.u.settime.secs        = xentime.tv_sec;
+               op.u.settime.usecs       = xentime.tv_nsec / NSEC_PER_USEC;
+               op.u.settime.system_time = shadow_system_time;
+               write_sequnlock_irq(&xtime_lock);
+               HYPERVISOR_dom0_op(&op);
+       } else
+ #endif
+               write_sequnlock_irq(&xtime_lock);
+       clock_was_set();
+       return 0;
+ }
+ EXPORT_SYMBOL(do_settimeofday);
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ static int set_rtc_mmss(unsigned long nowtime)
+ {
+       int retval;
+       /* gets recalled with irq locally disabled */
+       spin_lock(&rtc_lock);
+       if (efi_enabled)
+               retval = efi_set_rtc_mmss(nowtime);
+       else
+               retval = mach_set_rtc_mmss(nowtime);
+       spin_unlock(&rtc_lock);
+       return retval;
+ }
+ #endif
+ /* monotonic_clock(): returns # of nanoseconds passed since time_init()
+  *            Note: This function is required to return accurate
+  *            time even in the absence of multiple timer ticks.
+  */
+ unsigned long long monotonic_clock(void)
+ {
+       return cur_timer->monotonic_clock();
+ }
+ EXPORT_SYMBOL(monotonic_clock);
+ #if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
+ unsigned long profile_pc(struct pt_regs *regs)
+ {
+       unsigned long pc = instruction_pointer(regs);
+       if (in_lock_functions(pc))
+               return *(unsigned long *)(regs->ebp + 4);
+       return pc;
+ }
+ EXPORT_SYMBOL(profile_pc);
+ #endif
+ /*
+  * timer_interrupt() needs to keep up the real-time clock,
+  * as well as call the "do_timer()" routine every clocktick
+  */
+ static inline void do_timer_interrupt(int irq, void *dev_id,
+                                       struct pt_regs *regs)
+ {
+       time_t wtm_sec, sec;
+       s64 delta, nsec;
+       long sec_diff, wtm_nsec;
+       do {
+               __get_time_values_from_xen();
+               delta = (s64)(shadow_system_time +
+                             ((s64)cur_timer->get_offset() * 
+                              (s64)NSEC_PER_USEC) -
+                             processed_system_time);
+       }
+       while (!TIME_VALUES_UP_TO_DATE);
+       if (unlikely(delta < 0)) {
+               printk("Timer ISR: Time went backwards: %lld %lld %lld %lld\n",
+                      delta, shadow_system_time,
+                      ((s64)cur_timer->get_offset() * (s64)NSEC_PER_USEC), 
+                      processed_system_time);
+               return;
+       }
+       /* Process elapsed jiffies since last call. */
+       while (delta >= NS_PER_TICK) {
+               delta -= NS_PER_TICK;
+               processed_system_time += NS_PER_TICK;
+               do_timer(regs);
 -#endif
+               update_process_times(user_mode(regs));
 -                  profile_tick(CPU_PROFILING, regs);
+               if (regs)
 -       * would first get locked out. It is safe against normal
 -       * updates of jiffies since interrupts are off.
++                      profile_tick(CPU_PROFILING, regs);
+       }
+       /*
+        * Take synchronised time from Xen once a minute if we're not
+        * synchronised ourselves, and we haven't chosen to keep an independent
+        * time base.
+        */
+       if (!INDEPENDENT_WALLCLOCK() &&
+           ((time_status & STA_UNSYNC) != 0) &&
+           (xtime.tv_sec > (last_update_from_xen + 60))) {
+               /* Adjust shadow for jiffies that haven't updated xtime yet. */
+               shadow_tv.tv_usec -= 
+                       (jiffies - wall_jiffies) * (USEC_PER_SEC / HZ);
+               HANDLE_USEC_UNDERFLOW(shadow_tv);
+               /*
+                * Reset our running time counts if they are invalidated by
+                * a warp backwards of more than 500ms.
+                */
+               sec_diff = xtime.tv_sec - shadow_tv.tv_sec;
+               if (unlikely(abs(sec_diff) > 1) ||
+                   unlikely(((sec_diff * USEC_PER_SEC) +
+                             (xtime.tv_nsec / NSEC_PER_USEC) -
+                             shadow_tv.tv_usec) > 500000)) {
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+                       last_rtc_update = last_update_to_xen = 0;
+ #endif
+                       last_seen_tv.tv_sec = 0;
+               }
+               /* Update our unsynchronised xtime appropriately. */
+               sec = shadow_tv.tv_sec;
+               nsec = shadow_tv.tv_usec * NSEC_PER_USEC;
+               __normalize_time(&sec, &nsec);
+               wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+               wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+               set_normalized_timespec(&xtime, sec, nsec);
+               set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+               last_update_from_xen = sec;
+       }
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+       if (!(xen_start_info.flags & SIF_INITDOMAIN))
+               return;
+       /* Send synchronised time to Xen approximately every minute. */
+       if (((time_status & STA_UNSYNC) == 0) &&
+           (xtime.tv_sec > (last_update_to_xen + 60))) {
+               dom0_op_t op;
+               struct timeval tv;
+               tv.tv_sec   = xtime.tv_sec;
+               tv.tv_usec  = xtime.tv_nsec / NSEC_PER_USEC;
+               tv.tv_usec += (jiffies - wall_jiffies) * (USEC_PER_SEC/HZ);
+               HANDLE_USEC_OVERFLOW(tv);
+               op.cmd = DOM0_SETTIME;
+               op.u.settime.secs        = tv.tv_sec;
+               op.u.settime.usecs       = tv.tv_usec;
+               op.u.settime.system_time = shadow_system_time;
+               HYPERVISOR_dom0_op(&op);
+               last_update_to_xen = xtime.tv_sec;
+       }
+       /*
+        * If we have an externally synchronized Linux clock, then update
+        * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+        * called as close as possible to 500 ms before the new second starts.
+        */
+       if ((time_status & STA_UNSYNC) == 0 &&
+           xtime.tv_sec > last_rtc_update + 660 &&
+           (xtime.tv_nsec / 1000)
+                       >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
+           (xtime.tv_nsec / 1000)
+                       <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) {
+               /* horrible...FIXME */
+               if (efi_enabled) {
+                       if (efi_set_rtc_mmss(xtime.tv_sec) == 0)
+                               last_rtc_update = xtime.tv_sec;
+                       else
+                               last_rtc_update = xtime.tv_sec - 600;
+               } else if (set_rtc_mmss(xtime.tv_sec) == 0)
+                       last_rtc_update = xtime.tv_sec;
+               else
+                       last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+       }
+ #endif
+ }
+ /*
+  * This is the same as the above, except we _also_ save the current
+  * Time Stamp Counter value at the time of the timer interrupt, so that
+  * we later on can estimate the time of day more exactly.
+  */
+ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ {
+       /*
+        * Here we are in the timer irq handler. We just have irqs locally
+        * disabled but we don't know if the timer_bh is running on the other
+        * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+        * the irq version of write_lock because as just said we have irq
+        * locally disabled. -arca
+        */
+       write_seqlock(&xtime_lock);
+       do_timer_interrupt(irq, NULL, regs);
+       write_sequnlock(&xtime_lock);
+       return IRQ_HANDLED;
+ }
+ /* not static: needed by APM */
+ unsigned long get_cmos_time(void)
+ {
+       unsigned long retval;
+       spin_lock(&rtc_lock);
+       if (efi_enabled)
+               retval = efi_get_time();
+       else
+               retval = mach_get_cmos_time();
+       spin_unlock(&rtc_lock);
+       return retval;
+ }
+ static long clock_cmos_diff, sleep_start;
+ static int timer_suspend(struct sys_device *dev, u32 state)
+ {
+       /*
+        * Estimate time zone so that set_time can update the clock
+        */
+       clock_cmos_diff = -get_cmos_time();
+       clock_cmos_diff += get_seconds();
+       sleep_start = get_cmos_time();
+       return 0;
+ }
+ static int timer_resume(struct sys_device *dev)
+ {
+       unsigned long flags;
+       unsigned long sec;
+       unsigned long sleep_length;
+ #ifdef CONFIG_HPET_TIMER
+       if (is_hpet_enabled())
+               hpet_reenable();
+ #endif
+       sec = get_cmos_time() + clock_cmos_diff;
+       sleep_length = get_cmos_time() - sleep_start;
+       write_seqlock_irqsave(&xtime_lock, flags);
+       xtime.tv_sec = sec;
+       xtime.tv_nsec = 0;
+       write_sequnlock_irqrestore(&xtime_lock, flags);
+       jiffies += sleep_length * HZ;
+       return 0;
+ }
+ static struct sysdev_class timer_sysclass = {
+       .resume = timer_resume,
+       .suspend = timer_suspend,
+       set_kset_name("timer"),
+ };
+ /* XXX this driverfs stuff should probably go elsewhere later -john */
+ static struct sys_device device_timer = {
+       .id     = 0,
+       .cls    = &timer_sysclass,
+ };
+ static int time_init_device(void)
+ {
+       int error = sysdev_class_register(&timer_sysclass);
+       if (!error)
+               error = sysdev_register(&device_timer);
+       return error;
+ }
+ device_initcall(time_init_device);
+ #ifdef CONFIG_HPET_TIMER
+ extern void (*late_time_init)(void);
+ /* Duplicate of time_init() below, with hpet_enable part added */
+ void __init hpet_time_init(void)
+ {
+       xtime.tv_sec = get_cmos_time();
+       xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+       set_normalized_timespec(&wall_to_monotonic,
+               -xtime.tv_sec, -xtime.tv_nsec);
+       if (hpet_enable() >= 0) {
+               printk("Using HPET for base-timer\n");
+       }
+       cur_timer = select_timer();
+       printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
+       time_init_hook();
+ }
+ #endif
+ /* Dynamically-mapped IRQ. */
+ static int TIMER_IRQ;
+ static struct irqaction irq_timer = {
+       timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer",
+       NULL, NULL
+ };
+ void __init time_init(void)
+ {
+ #ifdef CONFIG_HPET_TIMER
+       if (is_hpet_capable()) {
+               /*
+                * HPET initialization needs to do memory-mapped io. So, let
+                * us do a late initialization after mem_init().
+                */
+               late_time_init = hpet_time_init;
+               return;
+       }
+ #endif
+       __get_time_values_from_xen();
+       xtime.tv_sec = shadow_tv.tv_sec;
+       xtime.tv_nsec = shadow_tv.tv_usec * NSEC_PER_USEC;
+       set_normalized_timespec(&wall_to_monotonic,
+               -xtime.tv_sec, -xtime.tv_nsec);
+       processed_system_time = shadow_system_time;
+       if (timer_tsc_init.init(NULL) != 0)
+               BUG();
+       printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
+       TIMER_IRQ = bind_virq_to_irq(VIRQ_TIMER);
+       (void)setup_irq(TIMER_IRQ, &irq_timer);
+ }
+ /* Convert jiffies to system time. Call with xtime_lock held for reading. */
+ static inline u64 __jiffies_to_st(unsigned long j) 
+ {
+       return processed_system_time + ((j - jiffies) * NS_PER_TICK);
+ }
+ /*
+  * This function works out when the the next timer function has to be
+  * executed (by looking at the timer list) and sets the Xen one-shot
+  * domain timer to the appropriate value. This is typically called in
+  * cpu_idle() before the domain blocks.
+  * 
+  * The function returns a non-0 value on error conditions.
+  * 
+  * It must be called with interrupts disabled.
+  */
+ int set_timeout_timer(void)
+ {
+       u64 alarm = 0;
+       int ret = 0;
++#ifdef CONFIG_SMP
++      unsigned long seq;
++#endif
+       /*
+        * This is safe against long blocking (since calculations are
+        * not based on TSC deltas). It is also safe against warped
+        * system time since suspend-resume is cooperative and we
++       * would first get locked out.
+        */
++#ifdef CONFIG_SMP
++      do {
++              seq = read_seqbegin(&xtime_lock);
++              if (smp_processor_id())
++                      alarm = __jiffies_to_st(jiffies + 1);
++              else
++                      alarm = __jiffies_to_st(jiffies + 1);
++      } while (read_seqretry(&xtime_lock, seq));
++#else
+       alarm = __jiffies_to_st(next_timer_interrupt());
++#endif
+       /* Failure is pretty bad, but we'd best soldier on. */
+       if ( HYPERVISOR_set_timer_op(alarm) != 0 )
+               ret = -1;
+       return ret;
+ }
+ void time_suspend(void)
+ {
+       /* nothing */
+ }
+ /* No locking required. We are only CPU running, and interrupts are off. */
+ void time_resume(void)
+ {
+       if (timer_tsc_init.init(NULL) != 0)
+               BUG();
+       /* Get timebases for new environment. */ 
+       __get_time_values_from_xen();
+       /* Reset our own concept of passage of system time. */
+       processed_system_time = shadow_system_time;
+       /* Accept a warp in UTC (wall-clock) time. */
+       last_seen_tv.tv_sec = 0;
+       /* Make sure we resync UTC time with Xen on next timer interrupt. */
+       last_update_from_xen = 0;
+ }
++#ifdef CONFIG_SMP
++#define xxprint(msg) HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg)
++
++static irqreturn_t local_timer_interrupt(int irq, void *dev_id,
++                                       struct pt_regs *regs)
++{
++      s64 delta;
++      int cpu = smp_processor_id();
++
++      do {
++              __get_time_values_from_xen();
++
++              delta = (s64)(shadow_system_time +
++                            ((s64)cur_timer->get_offset() * 
++                             (s64)NSEC_PER_USEC) -
++                            per_cpu(processed_system_time, cpu));
++      }
++      while (!TIME_VALUES_UP_TO_DATE);
++
++      if (unlikely(delta < 0)) {
++              printk("Timer ISR/%d: Time went backwards: %lld %lld %lld %lld\n",
++                     cpu, delta, shadow_system_time,
++                     ((s64)cur_timer->get_offset() * (s64)NSEC_PER_USEC), 
++                     processed_system_time);
++              return IRQ_HANDLED;
++      }
++
++      /* Process elapsed jiffies since last call. */
++      while (delta >= NS_PER_TICK) {
++              delta -= NS_PER_TICK;
++              per_cpu(processed_system_time, cpu) += NS_PER_TICK;
++              if (regs)
++                      update_process_times(user_mode(regs));
++#if 0
++              if (regs)
++                      profile_tick(CPU_PROFILING, regs);
++#endif
++      }
++
++      if (smp_processor_id() == 0) {
++          xxprint("bug bug\n");
++          BUG();
++      }
++
++      return IRQ_HANDLED;
++}
++
++static struct irqaction local_irq_timer = {
++      local_timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "ltimer",
++      NULL, NULL
++};
++
++void local_setup_timer(void)
++{
++      int seq, time_irq;
++      int cpu = smp_processor_id();
++
++      do {
++          seq = read_seqbegin(&xtime_lock);
++          per_cpu(processed_system_time, cpu) = shadow_system_time;
++      } while (read_seqretry(&xtime_lock, seq));
++
++      time_irq = bind_virq_to_irq(VIRQ_TIMER);
++      (void)setup_irq(time_irq, &local_irq_timer);
++}
++#endif
++
+ /*
+  * /proc/sys/xen: This really belongs in another file. It can stay here for
+  * now however.
+  */
+ static ctl_table xen_subtable[] = {
+       {1, "independent_wallclock", &independent_wallclock,
+        sizeof(independent_wallclock), 0644, NULL, proc_dointvec},
+       {0}
+ };
+ static ctl_table xen_table[] = {
+       {123, "xen", NULL, 0, 0555, xen_subtable},
+       {0}
+ };
+ static int __init xen_sysctl_init(void)
+ {
+       (void)register_sysctl_table(xen_table, 0);
+       return 0;
+ }
+ __initcall(xen_sysctl_init);
index 0000000000000000000000000000000000000000,1936d96c37af41dcf82aa383329733247b883986..829ba1f5c23c967ac80c918d2470a401252fded6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,989 +1,1001 @@@
+ /*
+  *  linux/arch/i386/traps.c
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  *
+  *  Pentium III FXSR, SSE support
+  *    Gareth Hughes <gareth@valinux.com>, May 2000
+  */
+ /*
+  * 'Traps.c' handles hardware traps and faults after we have saved some
+  * state in 'asm.s'.
+  */
+ #include <linux/config.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+ #include <linux/errno.h>
+ #include <linux/timer.h>
+ #include <linux/mm.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+ #include <linux/interrupt.h>
+ #include <linux/highmem.h>
+ #include <linux/kallsyms.h>
+ #include <linux/ptrace.h>
+ #include <linux/utsname.h>
+ #include <linux/kprobes.h>
+ #ifdef CONFIG_EISA
+ #include <linux/ioport.h>
+ #include <linux/eisa.h>
+ #endif
+ #ifdef CONFIG_MCA
+ #include <linux/mca.h>
+ #endif
+ #include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/atomic.h>
+ #include <asm/debugreg.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+ #include <asm/nmi.h>
+ #include <asm/smp.h>
+ #include <asm/arch_hooks.h>
+ #include <asm/kdebug.h>
+ #include <linux/irq.h>
+ #include <linux/module.h>
+ #include "mach_traps.h"
+ asmlinkage int system_call(void);
+ /* Do we ignore FPU interrupts ? */
+ char ignore_fpu_irq = 0;
+ /*
+  * The IDT has to be page-aligned to simplify the Pentium
+  * F0 0F bug workaround.. We have a special link segment
+  * for this.
+  */
+ struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
+ asmlinkage void divide_error(void);
+ asmlinkage void debug(void);
+ asmlinkage void nmi(void);
+ asmlinkage void int3(void);
+ asmlinkage void overflow(void);
+ asmlinkage void bounds(void);
+ asmlinkage void invalid_op(void);
+ asmlinkage void device_not_available(void);
+ asmlinkage void coprocessor_segment_overrun(void);
+ asmlinkage void invalid_TSS(void);
+ asmlinkage void segment_not_present(void);
+ asmlinkage void stack_segment(void);
+ asmlinkage void general_protection(void);
+ asmlinkage void page_fault(void);
+ asmlinkage void coprocessor_error(void);
+ asmlinkage void simd_coprocessor_error(void);
+ asmlinkage void alignment_check(void);
+ asmlinkage void fixup_4gb_segment(void);
+ asmlinkage void machine_check(void);
+ static int kstack_depth_to_print = 24;
+ struct notifier_block *i386die_chain;
+ static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED;
+ int register_die_notifier(struct notifier_block *nb)
+ {
+       int err = 0;
+       unsigned long flags;
+       spin_lock_irqsave(&die_notifier_lock, flags);
+       err = notifier_chain_register(&i386die_chain, nb);
+       spin_unlock_irqrestore(&die_notifier_lock, flags);
+       return err;
+ }
+ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+ {
+       return  p > (void *)tinfo &&
+               p < (void *)tinfo + THREAD_SIZE - 3;
+ }
+ static inline unsigned long print_context_stack(struct thread_info *tinfo,
+                               unsigned long *stack, unsigned long ebp)
+ {
+       unsigned long addr;
+ #ifdef        CONFIG_FRAME_POINTER
+       while (valid_stack_ptr(tinfo, (void *)ebp)) {
+               addr = *(unsigned long *)(ebp + 4);
+               printk(" [<%08lx>] ", addr);
+               print_symbol("%s", addr);
+               printk("\n");
+               ebp = *(unsigned long *)ebp;
+       }
+ #else
+       while (valid_stack_ptr(tinfo, stack)) {
+               addr = *stack++;
+               if (__kernel_text_address(addr)) {
+                       printk(" [<%08lx>]", addr);
+                       print_symbol(" %s", addr);
+                       printk("\n");
+               }
+       }
+ #endif
+       return ebp;
+ }
+ void show_trace(struct task_struct *task, unsigned long * stack)
+ {
+       unsigned long ebp;
+       if (!task)
+               task = current;
+       if (task == current) {
+               /* Grab ebp right from our regs */
+               asm ("movl %%ebp, %0" : "=r" (ebp) : );
+       } else {
+               /* ebp is the last reg pushed by switch_to */
+               ebp = *(unsigned long *) task->thread.esp;
+       }
+       while (1) {
+               struct thread_info *context;
+               context = (struct thread_info *)
+                       ((unsigned long)stack & (~(THREAD_SIZE - 1)));
+               ebp = print_context_stack(context, stack, ebp);
+               stack = (unsigned long*)context->previous_esp;
+               if (!stack)
+                       break;
+               printk(" =======================\n");
+       }
+ }
+ void show_stack(struct task_struct *task, unsigned long *esp)
+ {
+       unsigned long *stack;
+       int i;
+       if (esp == NULL) {
+               if (task)
+                       esp = (unsigned long*)task->thread.esp;
+               else
+                       esp = (unsigned long *)&esp;
+       }
+       stack = esp;
+       for(i = 0; i < kstack_depth_to_print; i++) {
+               if (kstack_end(stack))
+                       break;
+               if (i && ((i % 8) == 0))
+                       printk("\n       ");
+               printk("%08lx ", *stack++);
+       }
+       printk("\nCall Trace:\n");
+       show_trace(task, esp);
+ }
+ /*
+  * The architecture-independent dump_stack generator
+  */
+ void dump_stack(void)
+ {
+       unsigned long stack;
+       show_trace(current, &stack);
+ }
+ EXPORT_SYMBOL(dump_stack);
+ void show_registers(struct pt_regs *regs)
+ {
+       int i;
+       int in_kernel = 1;
+       unsigned long esp;
+       unsigned short ss;
+       esp = (unsigned long) (&regs->esp);
+       ss = __KERNEL_DS;
+       if (regs->xcs & 2) {
+               in_kernel = 0;
+               esp = regs->esp;
+               ss = regs->xss & 0xffff;
+       }
+       print_modules();
+       printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s VLI\nEFLAGS: %08lx"
+                       "   (%s) \n",
+               smp_processor_id(), 0xffff & regs->xcs, regs->eip,
+               print_tainted(), regs->eflags, system_utsname.release);
+       print_symbol("EIP is at %s\n", regs->eip);
+       printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
+               regs->eax, regs->ebx, regs->ecx, regs->edx);
+       printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
+               regs->esi, regs->edi, regs->ebp, esp);
+       printk("ds: %04x   es: %04x   ss: %04x\n",
+               regs->xds & 0xffff, regs->xes & 0xffff, ss);
+       printk("Process %s (pid: %d, threadinfo=%p task=%p)",
+               current->comm, current->pid, current_thread_info(), current);
+       /*
+        * When in-kernel, we also print out the stack and code at the
+        * time of the fault..
+        */
+       if (in_kernel) {
+               u8 *eip;
+               printk("\nStack: ");
+               show_stack(NULL, (unsigned long*)esp);
+               printk("Code: ");
+               eip = (u8 *)regs->eip - 43;
+               for (i = 0; i < 64; i++, eip++) {
+                       unsigned char c;
+                       if (eip < (u8 *)PAGE_OFFSET || __get_user(c, eip)) {
+                               printk(" Bad EIP value.");
+                               break;
+                       }
+                       if (eip == (u8 *)regs->eip)
+                               printk("<%02x> ", c);
+                       else
+                               printk("%02x ", c);
+               }
+       }
+       printk("\n");
+ }     
+ static void handle_BUG(struct pt_regs *regs)
+ {
+       unsigned short ud2;
+       unsigned short line;
+       char *file;
+       char c;
+       unsigned long eip;
+       if (regs->xcs & 2)
+               goto no_bug;            /* Not in kernel */
+       eip = regs->eip;
+       if (eip < PAGE_OFFSET)
+               goto no_bug;
+       if (__get_user(ud2, (unsigned short *)eip))
+               goto no_bug;
+       if (ud2 != 0x0b0f)
+               goto no_bug;
+       if (__get_user(line, (unsigned short *)(eip + 2)))
+               goto bug;
+       if (__get_user(file, (char **)(eip + 4)) ||
+               (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
+               file = "<bad filename>";
+       printk("------------[ cut here ]------------\n");
+       printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line);
+ no_bug:
+       return;
+       /* Here we know it was a BUG but file-n-line is unavailable */
+ bug:
+       printk("Kernel BUG\n");
+ }
+ void die(const char * str, struct pt_regs * regs, long err)
+ {
+       static struct {
+               spinlock_t lock;
+               u32 lock_owner;
+               int lock_owner_depth;
+       } die = {
+               .lock =                 SPIN_LOCK_UNLOCKED,
+               .lock_owner =           -1,
+               .lock_owner_depth =     0
+       };
+       static int die_counter;
+       if (die.lock_owner != smp_processor_id()) {
+               console_verbose();
+               spin_lock_irq(&die.lock);
+               die.lock_owner = smp_processor_id();
+               die.lock_owner_depth = 0;
+               bust_spinlocks(1);
+       }
+       if (++die.lock_owner_depth < 3) {
+               int nl = 0;
+               handle_BUG(regs);
+               printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+ #ifdef CONFIG_PREEMPT
+               printk("PREEMPT ");
+               nl = 1;
+ #endif
+ #ifdef CONFIG_SMP
+               printk("SMP ");
+               nl = 1;
+ #endif
+ #ifdef CONFIG_DEBUG_PAGEALLOC
+               printk("DEBUG_PAGEALLOC");
+               nl = 1;
+ #endif
+               if (nl)
+                       printk("\n");
+       notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
+               show_registers(regs);
+       } else
+               printk(KERN_ERR "Recursive die() failure, output suppressed\n");
+       bust_spinlocks(0);
+       die.lock_owner = -1;
+       spin_unlock_irq(&die.lock);
+       if (in_interrupt())
+               panic("Fatal exception in interrupt");
+       if (panic_on_oops) {
+               printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(5 * HZ);
+               panic("Fatal exception");
+       }
+       do_exit(SIGSEGV);
+ }
+ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+ {
+       if (!(regs->eflags & VM_MASK) && !(2 & regs->xcs))
+               die(str, regs, err);
+ }
+ static void do_trap(int trapnr, int signr, char *str, int vm86,
+                          struct pt_regs * regs, long error_code, siginfo_t *info)
+ {
+       if (regs->eflags & VM_MASK) {
+               if (vm86)
+                       goto vm86_trap;
+               goto trap_signal;
+       }
+       if (!(regs->xcs & 2))
+               goto kernel_trap;
+       trap_signal: {
+               struct task_struct *tsk = current;
+               tsk->thread.error_code = error_code;
+               tsk->thread.trap_no = trapnr;
+               if (info)
+                       force_sig_info(signr, info, tsk);
+               else
+                       force_sig(signr, tsk);
+               return;
+       }
+       kernel_trap: {
+               if (!fixup_exception(regs))
+                       die(str, regs, error_code);
+               return;
+       }
+       vm86_trap: {
+               int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr);
+               if (ret) goto trap_signal;
+               return;
+       }
+ }
+ #define DO_ERROR(trapnr, signr, str, name) \
+ fastcall void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+                                               == NOTIFY_STOP) \
+               return; \
+       do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
+ }
+ #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+ fastcall void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+       siginfo_t info; \
+       info.si_signo = signr; \
+       info.si_errno = 0; \
+       info.si_code = sicode; \
+       info.si_addr = (void __user *)siaddr; \
+       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+                                               == NOTIFY_STOP) \
+               return; \
+       do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
+ }
+ #define DO_VM86_ERROR(trapnr, signr, str, name) \
+ fastcall void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+                                               == NOTIFY_STOP) \
+               return; \
+       do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
+ }
+ #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+ fastcall void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+       siginfo_t info; \
+       info.si_signo = signr; \
+       info.si_errno = 0; \
+       info.si_code = sicode; \
+       info.si_addr = (void __user *)siaddr; \
+       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+                                               == NOTIFY_STOP) \
+               return; \
+       do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
+ }
+ DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->eip)
+ #ifndef CONFIG_KPROBES
+ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
+ #endif
+ DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
+ DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
+ DO_ERROR_INFO( 6, SIGILL,  "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
+ DO_VM86_ERROR( 7, SIGSEGV, "device not available", device_not_available)
+ DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+ DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
+ DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
+ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+ #ifdef CONFIG_X86_MCE
+ DO_ERROR(18, SIGBUS, "machine check", machine_check)
+ #endif
+ fastcall void do_general_protection(struct pt_regs * regs, long error_code)
+ {
+       /*
+        * If we trapped on an LDT access then ensure that the default_ldt is
+        * loaded, if nothing else. We load default_ldt lazily because LDT
+        * switching costs time and many applications don't need it.
+        */
+       if (unlikely((error_code & 6) == 4)) {
+               unsigned long ldt;
+               __asm__ __volatile__ ("sldt %0" : "=r" (ldt));
+               if (ldt == 0) {
+                       mmu_update_t u;
+                       u.ptr = MMU_EXTENDED_COMMAND;
+                       u.ptr |= (unsigned long)&default_ldt[0];
+                       u.val = MMUEXT_SET_LDT | (5 << MMUEXT_CMD_SHIFT);
+                       if (unlikely(HYPERVISOR_mmu_update(&u, 1, NULL) < 0)) {
+                               show_trace(NULL, (unsigned long *)&u);
+                               panic("Failed to install default LDT");
+                       }
+                       return;
+               }
+       }
+       if (regs->eflags & VM_MASK)
+               goto gp_in_vm86;
+       if (!(regs->xcs & 2))
+               goto gp_in_kernel;
+       current->thread.error_code = error_code;
+       current->thread.trap_no = 13;
+       force_sig(SIGSEGV, current);
+       return;
+ gp_in_vm86:
+       local_irq_enable();
+       handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
+       return;
+ gp_in_kernel:
+       if (!fixup_exception(regs)) {
+               if (notify_die(DIE_GPF, "general protection fault", regs,
+                               error_code, 13, SIGSEGV) == NOTIFY_STOP)
+                       return;
+               die("general protection fault", regs, error_code);
+       }
+ }
+ static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ {
+       printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
+       printk("You probably have a hardware problem with your RAM chips\n");
+       /* Clear and disable the memory parity error line. */
+       clear_mem_error(reason);
+ }
+ static void io_check_error(unsigned char reason, struct pt_regs * regs)
+ {
+       unsigned long i;
+       printk("NMI: IOCK error (debug interrupt?)\n");
+       show_registers(regs);
+       /* Re-enable the IOCK line, wait for a few seconds */
+       reason = (reason & 0xf) | 8;
+       outb(reason, 0x61);
+       i = 2000;
+       while (--i) udelay(1000);
+       reason &= ~8;
+       outb(reason, 0x61);
+ }
+ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+ {
+ #ifdef CONFIG_MCA
+       /* Might actually be able to figure out what the guilty party
+       * is. */
+       if( MCA_bus ) {
+               mca_handle_nmi();
+               return;
+       }
+ #endif
+       printk("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+               reason, smp_processor_id());
+       printk("Dazed and confused, but trying to continue\n");
+       printk("Do you have a strange power saving mode enabled?\n");
+ }
+ static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
+ void die_nmi (struct pt_regs *regs, const char *msg)
+ {
+       spin_lock(&nmi_print_lock);
+       /*
+       * We are in trouble anyway, lets at least try
+       * to get a message out.
+       */
+       bust_spinlocks(1);
+       printk(msg);
+       printk(" on CPU%d, eip %08lx, registers:\n",
+               smp_processor_id(), regs->eip);
+       show_registers(regs);
+       printk("console shuts up ...\n");
+       console_silent();
+       spin_unlock(&nmi_print_lock);
+       bust_spinlocks(0);
+       do_exit(SIGSEGV);
+ }
+ static void default_do_nmi(struct pt_regs * regs)
+ {
+       unsigned char reason = 0;
+       /* Only the BSP gets external NMIs from the system.  */
+       if (!smp_processor_id())
+               reason = get_nmi_reason();
+  
+       if (!(reason & 0xc0)) {
+               if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
+                                                       == NOTIFY_STOP)
+                       return;
+ #ifdef CONFIG_X86_LOCAL_APIC
+               /*
+                * Ok, so this is none of the documented NMI sources,
+                * so it must be the NMI watchdog.
+                */
+               if (nmi_watchdog) {
+                       nmi_watchdog_tick(regs);
+                       return;
+               }
+ #endif
+               unknown_nmi_error(reason, regs);
+               return;
+       }
+       if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
+               return;
+       if (reason & 0x80)
+               mem_parity_error(reason, regs);
+       if (reason & 0x40)
+               io_check_error(reason, regs);
+       /*
+        * Reassert NMI in case it became active meanwhile
+        * as it's edge-triggered.
+        */
+       reassert_nmi();
+ }
+ static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
+ {
+       return 0;
+ }
+  
+ static nmi_callback_t nmi_callback = dummy_nmi_callback;
+  
+ fastcall void do_nmi(struct pt_regs * regs, long error_code)
+ {
+       int cpu;
+       nmi_enter();
+       cpu = smp_processor_id();
+       ++nmi_count(cpu);
+       if (!nmi_callback(regs, cpu))
+               default_do_nmi(regs);
+       nmi_exit();
+ }
+ void set_nmi_callback(nmi_callback_t callback)
+ {
+       nmi_callback = callback;
+ }
+ void unset_nmi_callback(void)
+ {
+       nmi_callback = dummy_nmi_callback;
+ }
+ #ifdef CONFIG_KPROBES
+ fastcall int do_int3(struct pt_regs *regs, long error_code)
+ {
+       if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+                       == NOTIFY_STOP)
+               return 1;
+       /* This is an interrupt gate, because kprobes wants interrupts
+       disabled.  Normal trap handlers don't. */
+       restore_interrupts(regs);
+       do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
+       return 0;
+ }
+ #endif
+ /*
+  * Our handling of the processor debug registers is non-trivial.
+  * We do not clear them on entry and exit from the kernel. Therefore
+  * it is possible to get a watchpoint trap here from inside the kernel.
+  * However, the code in ./ptrace.c has ensured that the user can
+  * only set watchpoints on userspace addresses. Therefore the in-kernel
+  * watchpoint trap can only occur in code which is reading/writing
+  * from user space. Such code must not hold kernel locks (since it
+  * can equally take a page fault), therefore it is safe to call
+  * force_sig_info even though that claims and releases locks.
+  * 
+  * Code in ./signal.c ensures that the debug control register
+  * is restored before we deliver any signal, and therefore that
+  * user code runs with the correct debug control register even though
+  * we clear it here.
+  *
+  * Being careful here means that we don't have to be as careful in a
+  * lot of more complicated places (task switching can be a bit lazy
+  * about restoring all the debug state, and ptrace doesn't have to
+  * find every occurrence of the TF bit that could be saved away even
+  * by user code)
+  */
+ fastcall void do_debug(struct pt_regs * regs, long error_code)
+ {
+       unsigned int condition;
+       struct task_struct *tsk = current;
+       siginfo_t info;
+       condition = HYPERVISOR_get_debugreg(6);
+       if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+                                       SIGTRAP) == NOTIFY_STOP)
+               return;
+ #if 0
+       /* It's safe to allow irq's after DR6 has been saved */
+       if (regs->eflags & X86_EFLAGS_IF)
+               local_irq_enable();
+ #endif
+       /* Mask out spurious debug traps due to lazy DR7 setting */
+       if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+               if (!tsk->thread.debugreg[7])
+                       goto clear_dr7;
+       }
+       if (regs->eflags & VM_MASK)
+               goto debug_vm86;
+       /* Save debug status register where ptrace can see it */
+       tsk->thread.debugreg[6] = condition;
+       /* Mask out spurious TF errors due to lazy TF clearing */
+       if (condition & DR_STEP) {
+               /*
+                * The TF error should be masked out only if the current
+                * process is not traced and if the TRAP flag has been set
+                * previously by a tracing process (condition detected by
+                * the PT_DTRACE flag); remember that the i386 TRAP flag
+                * can be modified by the process itself in user mode,
+                * allowing programs to debug themselves without the ptrace()
+                * interface.
+                */
+               if ((regs->xcs & 2) == 0)
+                       goto clear_TF_reenable;
+               if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
+                       goto clear_TF;
+       }
+       /* Ok, finally something we can handle */
+       tsk->thread.trap_no = 1;
+       tsk->thread.error_code = error_code;
+       info.si_signo = SIGTRAP;
+       info.si_errno = 0;
+       info.si_code = TRAP_BRKPT;
+       
+       /* If this is a kernel mode trap, save the user PC on entry to 
+        * the kernel, that's what the debugger can make sense of.
+        */
+       info.si_addr = ((regs->xcs & 2) == 0) ? (void __user *)tsk->thread.eip
+                                             : (void __user *)regs->eip;
+       force_sig_info(SIGTRAP, &info, tsk);
+       /* Disable additional traps. They'll be re-enabled when
+        * the signal is delivered.
+        */
+ clear_dr7:
+       HYPERVISOR_set_debugreg(7, 0);
+       return;
+ debug_vm86:
+       handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
+       return;
+ clear_TF_reenable:
+       set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+ clear_TF:
+       regs->eflags &= ~TF_MASK;
+       return;
+ }
+ /*
+  * Note that we play around with the 'TS' bit in an attempt to get
+  * the correct behaviour even in the presence of the asynchronous
+  * IRQ13 behaviour
+  */
+ void math_error(void __user *eip)
+ {
+       struct task_struct * task;
+       siginfo_t info;
+       unsigned short cwd, swd;
+       /*
+        * Save the info for the exception handler and clear the error.
+        */
+       task = current;
+       save_init_fpu(task);
+       task->thread.trap_no = 16;
+       task->thread.error_code = 0;
+       info.si_signo = SIGFPE;
+       info.si_errno = 0;
+       info.si_code = __SI_FAULT;
+       info.si_addr = eip;
+       /*
+        * (~cwd & swd) will mask out exceptions that are not set to unmasked
+        * status.  0x3f is the exception bits in these regs, 0x200 is the
+        * C1 reg you need in case of a stack fault, 0x040 is the stack
+        * fault bit.  We should only be taking one exception at a time,
+        * so if this combination doesn't produce any single exception,
+        * then we have a bad program that isn't syncronizing its FPU usage
+        * and it will suffer the consequences since we won't be able to
+        * fully reproduce the context of the exception
+        */
+       cwd = get_fpu_cwd(task);
+       swd = get_fpu_swd(task);
+       switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
+               case 0x000:
+               default:
+                       break;
+               case 0x001: /* Invalid Op */
+               case 0x041: /* Stack Fault */
+               case 0x241: /* Stack Fault | Direction */
+                       info.si_code = FPE_FLTINV;
+                       /* Should we clear the SF or let user space do it ???? */
+                       break;
+               case 0x002: /* Denormalize */
+               case 0x010: /* Underflow */
+                       info.si_code = FPE_FLTUND;
+                       break;
+               case 0x004: /* Zero Divide */
+                       info.si_code = FPE_FLTDIV;
+                       break;
+               case 0x008: /* Overflow */
+                       info.si_code = FPE_FLTOVF;
+                       break;
+               case 0x020: /* Precision */
+                       info.si_code = FPE_FLTRES;
+                       break;
+       }
+       force_sig_info(SIGFPE, &info, task);
+ }
+ fastcall void do_coprocessor_error(struct pt_regs * regs, long error_code)
+ {
+       ignore_fpu_irq = 1;
+       math_error((void __user *)regs->eip);
+ }
+ void simd_math_error(void __user *eip)
+ {
+       struct task_struct * task;
+       siginfo_t info;
+       unsigned short mxcsr;
+       /*
+        * Save the info for the exception handler and clear the error.
+        */
+       task = current;
+       save_init_fpu(task);
+       task->thread.trap_no = 19;
+       task->thread.error_code = 0;
+       info.si_signo = SIGFPE;
+       info.si_errno = 0;
+       info.si_code = __SI_FAULT;
+       info.si_addr = eip;
+       /*
+        * The SIMD FPU exceptions are handled a little differently, as there
+        * is only a single status/control register.  Thus, to determine which
+        * unmasked exception was caught we must mask the exception mask bits
+        * at 0x1f80, and then use these to mask the exception bits at 0x3f.
+        */
+       mxcsr = get_fpu_mxcsr(task);
+       switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+               case 0x000:
+               default:
+                       break;
+               case 0x001: /* Invalid Op */
+                       info.si_code = FPE_FLTINV;
+                       break;
+               case 0x002: /* Denormalize */
+               case 0x010: /* Underflow */
+                       info.si_code = FPE_FLTUND;
+                       break;
+               case 0x004: /* Zero Divide */
+                       info.si_code = FPE_FLTDIV;
+                       break;
+               case 0x008: /* Overflow */
+                       info.si_code = FPE_FLTOVF;
+                       break;
+               case 0x020: /* Precision */
+                       info.si_code = FPE_FLTRES;
+                       break;
+       }
+       force_sig_info(SIGFPE, &info, task);
+ }
+ fastcall void do_simd_coprocessor_error(struct pt_regs * regs,
+                                         long error_code)
+ {
+       if (cpu_has_xmm) {
+               /* Handle SIMD FPU exceptions on PIII+ processors. */
+               ignore_fpu_irq = 1;
+               simd_math_error((void __user *)regs->eip);
+       } else {
+               /*
+                * Handle strange cache flush from user space exception
+                * in all other cases.  This is undocumented behaviour.
+                */
+               if (regs->eflags & VM_MASK) {
+                       handle_vm86_fault((struct kernel_vm86_regs *)regs,
+                                         error_code);
+                       return;
+               }
+               die_if_kernel("cache flush denied", regs, error_code);
+               current->thread.trap_no = 19;
+               current->thread.error_code = error_code;
+               force_sig(SIGSEGV, current);
+       }
+ }
+ /*
+  *  'math_state_restore()' saves the current math information in the
+  * old math state array, and gets the new ones from the current task
+  *
+  * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+  * Don't touch unless you *really* know how it works.
+  *
+  * Must be called with kernel preemption disabled (in this case,
+  * local interrupts are disabled at the call-site in entry.S).
+  */
+ asmlinkage void math_state_restore(struct pt_regs regs)
+ {
+       struct thread_info *thread = current_thread_info();
+       struct task_struct *tsk = thread->task;
+       /*
+        * A trap in kernel mode can be ignored. It'll be the fast XOR or
+        * copying libraries, which will correctly save/restore state and
+        * reset the TS bit in CR0.
+        */
+       if ((regs.xcs & 2) == 0)
+               return;
+       clts();         /* Allow maths ops (or we recurse) */
+       if (!tsk->used_math)
+               init_fpu(tsk);
+       restore_fpu(tsk);
+       thread->status |= TS_USEDFPU;   /* So we fnsave on switch_to() */
+ }
+ #ifndef CONFIG_MATH_EMULATION
+ asmlinkage void math_emulate(long arg)
+ {
+       printk("math-emulation not enabled and no coprocessor found.\n");
+       printk("killing %s.\n",current->comm);
+       force_sig(SIGFPE,current);
+       schedule();
+ }
+ #endif /* CONFIG_MATH_EMULATION */
+ #ifdef CONFIG_X86_F00F_BUG
+ void __init trap_init_f00f_bug(void)
+ {
+       __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
+       /*
+        * Update the IDT descriptor and reload the IDT so that
+        * it uses the read-only mapped virtual address.
+        */
+       idt_descr.address = fix_to_virt(FIX_F00F_IDT);
+       __asm__ __volatile__("lidt %0" : : "m" (idt_descr));
+ }
+ #endif
+ /* NB. All these are "trap gates" (i.e. events_mask isn't cleared). */
+ static trap_info_t trap_table[] = {
+       {  0, 0, __KERNEL_CS, (unsigned long)divide_error               },
+       {  1, 0, __KERNEL_CS, (unsigned long)debug                      },
+       {  3, 3, __KERNEL_CS, (unsigned long)int3                       },
+       {  4, 3, __KERNEL_CS, (unsigned long)overflow                   },
+       {  5, 3, __KERNEL_CS, (unsigned long)bounds                     },
+       {  6, 0, __KERNEL_CS, (unsigned long)invalid_op                 },
+       {  7, 0, __KERNEL_CS, (unsigned long)device_not_available       },
+       {  9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
+       { 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS                },
+       { 11, 0, __KERNEL_CS, (unsigned long)segment_not_present        },
+       { 12, 0, __KERNEL_CS, (unsigned long)stack_segment              },
+       { 13, 0, __KERNEL_CS, (unsigned long)general_protection         },
+       { 14, 0, __KERNEL_CS, (unsigned long)page_fault                 },
+       { 15, 0, __KERNEL_CS, (unsigned long)fixup_4gb_segment          },
+       { 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error          },
+       { 17, 0, __KERNEL_CS, (unsigned long)alignment_check            },
+ #ifdef CONFIG_X86_MCE
+       { 18, 0, __KERNEL_CS, (unsigned long)machine_check              },
+ #endif
+       { 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error     },
+       { SYSCALL_VECTOR,  3, __KERNEL_CS, (unsigned long)system_call   },
+       {  0, 0,           0, 0                                         }
+ };
+ void __init trap_init(void)
+ {
+       HYPERVISOR_set_trap_table(trap_table);
+       HYPERVISOR_set_fast_trap(SYSCALL_VECTOR);
+       /*
+        * default LDT is a single-entry callgate to lcall7 for iBCS
+        * and a callgate to lcall27 for Solaris/x86 binaries
+        */
+       make_lowmem_page_readonly(&default_ldt[0]);
+       xen_flush_page_update_queue();
+       /*
+        * Should be a barrier for any external CPU state.
+        */
+       cpu_init();
+ }
++
++int smp_trap_init(trap_info_t *trap_ctxt)
++{
++      trap_info_t *t = trap_table;
++
++      for (t = trap_table; t->address; t++) {
++              trap_ctxt[t->vector].flags = t->flags;
++              trap_ctxt[t->vector].cs = t->cs;
++              trap_ctxt[t->vector].address = t->address;
++      }
++      return SYSCALL_VECTOR;
++}
index 0000000000000000000000000000000000000000,b869fad317ce2ff57082266a312acf886f5d69cf..59ee3cb4f6c5ac97cd16a403ddc49b4a99786eed
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,554 +1,556 @@@
 -pgd_t *cur_pgd;                       /* XXXsmp */
+ /*
+  *  linux/arch/i386/mm/fault.c
+  *
+  *  Copyright (C) 1995  Linus Torvalds
+  */
+ #include <linux/signal.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/types.h>
+ #include <linux/ptrace.h>
+ #include <linux/mman.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/tty.h>
+ #include <linux/vt_kern.h>            /* For unblank_screen() */
+ #include <linux/highmem.h>
+ #include <linux/module.h>
++#include <linux/percpu.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <asm/desc.h>
+ #include <asm/kdebug.h>
+ extern void die(const char *,struct pt_regs *,long);
 -      page = ((unsigned long *) cur_pgd)[address >> 22];
++DEFINE_PER_CPU(pgd_t *, cur_pgd);
+ /*
+  * Unlock any spinlocks which will prevent us from getting the
+  * message out 
+  */
+ void bust_spinlocks(int yes)
+ {
+       int loglevel_save = console_loglevel;
+       if (yes) {
+               oops_in_progress = 1;
+               return;
+       }
+ #ifdef CONFIG_VT
+       unblank_screen();
+ #endif
+       oops_in_progress = 0;
+       /*
+        * OK, the message is on the console.  Now we call printk()
+        * without oops_in_progress set so that printk will give klogd
+        * a poke.  Hold onto your hats...
+        */
+       console_loglevel = 15;          /* NMI oopser may have shut the console up */
+       printk(" ");
+       console_loglevel = loglevel_save;
+ }
+ /*
+  * Return EIP plus the CS segment base.  The segment limit is also
+  * adjusted, clamped to the kernel/user address space (whichever is
+  * appropriate), and returned in *eip_limit.
+  *
+  * The segment is checked, because it might have been changed by another
+  * task between the original faulting instruction and here.
+  *
+  * If CS is no longer a valid code segment, or if EIP is beyond the
+  * limit, or if it is a kernel address when CS is not a kernel segment,
+  * then the returned value will be greater than *eip_limit.
+  * 
+  * This is slow, but is very rarely executed.
+  */
+ static inline unsigned long get_segment_eip(struct pt_regs *regs,
+                                           unsigned long *eip_limit)
+ {
+       unsigned long eip = regs->eip;
+       unsigned seg = regs->xcs & 0xffff;
+       u32 seg_ar, seg_limit, base, *desc;
+       /* The standard kernel/user address space limit. */
+       *eip_limit = (seg & 2) ? USER_DS.seg : KERNEL_DS.seg;
+       /* Unlikely, but must come before segment checks. */
+       if (unlikely((regs->eflags & VM_MASK) != 0))
+               return eip + (seg << 4);
+       
+       /* By far the most common cases. */
+       if (likely(seg == __USER_CS || seg == __KERNEL_CS))
+               return eip;
+       /* Check the segment exists, is within the current LDT/GDT size,
+          that kernel/user (ring 0..3) has the appropriate privilege,
+          that it's a code segment, and get the limit. */
+       __asm__ ("larl %3,%0; lsll %3,%1"
+                : "=&r" (seg_ar), "=r" (seg_limit) : "0" (0), "rm" (seg));
+       if ((~seg_ar & 0x9800) || eip > seg_limit) {
+               *eip_limit = 0;
+               return 1;        /* So that returned eip > *eip_limit. */
+       }
+       /* Get the GDT/LDT descriptor base. 
+          When you look for races in this code remember that
+          LDT and other horrors are only used in user space. */
+       if (seg & (1<<2)) {
+               /* Must lock the LDT while reading it. */
+               down(&current->mm->context.sem);
+               desc = current->mm->context.ldt;
+               desc = (void *)desc + (seg & ~7);
+       } else {
+               /* Must disable preemption while reading the GDT. */
+               desc = (u32 *)get_cpu_gdt_table(get_cpu());
+               desc = (void *)desc + (seg & ~7);
+       }
+       /* Decode the code segment base from the descriptor */
+       base =   (desc[0] >> 16) |
+               ((desc[1] & 0xff) << 16) |
+                (desc[1] & 0xff000000);
+       if (seg & (1<<2)) { 
+               up(&current->mm->context.sem);
+       } else
+               put_cpu();
+       /* Adjust EIP and segment limit, and clamp at the kernel limit.
+          It's legitimate for segments to wrap at 0xffffffff. */
+       seg_limit += base;
+       if (seg_limit < *eip_limit && seg_limit >= base)
+               *eip_limit = seg_limit;
+       return eip + base;
+ }
+ /* 
+  * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
+  * Check that here and ignore it.
+  */
+ static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
+ { 
+       unsigned long limit;
+       unsigned long instr = get_segment_eip (regs, &limit);
+       int scan_more = 1;
+       int prefetch = 0; 
+       int i;
+       for (i = 0; scan_more && i < 15; i++) { 
+               unsigned char opcode;
+               unsigned char instr_hi;
+               unsigned char instr_lo;
+               if (instr > limit)
+                       break;
+               if (__get_user(opcode, (unsigned char *) instr))
+                       break; 
+               instr_hi = opcode & 0xf0; 
+               instr_lo = opcode & 0x0f; 
+               instr++;
+               switch (instr_hi) { 
+               case 0x20:
+               case 0x30:
+                       /* Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes. */
+                       scan_more = ((instr_lo & 7) == 0x6);
+                       break;
+                       
+               case 0x60:
+                       /* 0x64 thru 0x67 are valid prefixes in all modes. */
+                       scan_more = (instr_lo & 0xC) == 0x4;
+                       break;          
+               case 0xF0:
+                       /* 0xF0, 0xF2, and 0xF3 are valid prefixes */
+                       scan_more = !instr_lo || (instr_lo>>1) == 1;
+                       break;                  
+               case 0x00:
+                       /* Prefetch instruction is 0x0F0D or 0x0F18 */
+                       scan_more = 0;
+                       if (instr > limit)
+                               break;
+                       if (__get_user(opcode, (unsigned char *) instr)) 
+                               break;
+                       prefetch = (instr_lo == 0xF) &&
+                               (opcode == 0x0D || opcode == 0x18);
+                       break;                  
+               default:
+                       scan_more = 0;
+                       break;
+               } 
+       }
+       return prefetch;
+ }
+ static inline int is_prefetch(struct pt_regs *regs, unsigned long addr,
+                             unsigned long error_code)
+ {
+       if (unlikely(boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+                    boot_cpu_data.x86 >= 6)) {
+               /* Catch an obscure case of prefetch inside an NX page. */
+               if (nx_enabled && (error_code & 16))
+                       return 0;
+               return __is_prefetch(regs, addr);
+       }
+       return 0;
+ } 
+ fastcall void do_invalid_op(struct pt_regs *, unsigned long);
+ /*
+  * This routine handles page faults.  It determines the address,
+  * and the problem, and then passes it off to one of the appropriate
+  * routines.
+  *
+  * error_code:
+  *    bit 0 == 0 means no page found, 1 means protection fault
+  *    bit 1 == 0 means read, 1 means write
+  *    bit 2 == 0 means kernel, 1 means user-mode
+  */
+ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code,
+                             unsigned long address)
+ {
+       struct task_struct *tsk;
+       struct mm_struct *mm;
+       struct vm_area_struct * vma;
+       unsigned long page;
+       int write;
+       siginfo_t info;
+       /* Set the "privileged fault" bit to something sane. */
+       error_code &= 3;
+       error_code |= (regs->xcs & 2) << 1;
+       if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+                                       SIGSEGV) == NOTIFY_STOP)
+               return;
+ #if 0
+       /* It's safe to allow irq's after cr2 has been saved */
+       if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
+               local_irq_enable();
+ #endif
+       tsk = current;
+       info.si_code = SEGV_MAPERR;
+       /*
+        * We fault-in kernel-space virtual memory on-demand. The
+        * 'reference' page table is init_mm.pgd.
+        *
+        * NOTE! We MUST NOT take any locks for this case. We may
+        * be in an interrupt or a critical region, and should
+        * only copy the information from the master page table,
+        * nothing more.
+        *
+        * This verifies that the fault happens in kernel space
+        * (error_code & 4) == 0, and that the fault was not a
+        * protection error (error_code & 1) == 0.
+        */
+       if (unlikely(address >= TASK_SIZE)) { 
+               if (!(error_code & 5))
+                       goto vmalloc_fault;
+               /* 
+                * Don't take the mm semaphore here. If we fixup a prefetch
+                * fault we could otherwise deadlock.
+                */
+               goto bad_area_nosemaphore;
+       } 
+       mm = tsk->mm;
+       /*
+        * If we're in an interrupt, have no user context or are running in an
+        * atomic region then we must not take the fault..
+        */
+       if (in_atomic() || !mm)
+               goto bad_area_nosemaphore;
+       /* When running in the kernel we expect faults to occur only to
+        * addresses in user space.  All other faults represent errors in the
+        * kernel and should generate an OOPS.  Unfortunatly, in the case of an
+        * erroneous fault occuring in a code path which already holds mmap_sem
+        * we will deadlock attempting to validate the fault against the
+        * address space.  Luckily the kernel only validly references user
+        * space from well defined areas of code, which are listed in the
+        * exceptions table.
+        *
+        * As the vast majority of faults will be valid we will only perform
+        * the source reference check when there is a possibilty of a deadlock.
+        * Attempt to lock the address space, if we cannot we then validate the
+        * source.  If this is invalid we can skip the address space check,
+        * thus avoiding the deadlock.
+        */
+       if (!down_read_trylock(&mm->mmap_sem)) {
+               if ((error_code & 4) == 0 &&
+                   !search_exception_tables(regs->eip))
+                       goto bad_area_nosemaphore;
+               down_read(&mm->mmap_sem);
+       }
+       vma = find_vma(mm, address);
+       if (!vma)
+               goto bad_area;
+       if (vma->vm_start <= address)
+               goto good_area;
+       if (!(vma->vm_flags & VM_GROWSDOWN))
+               goto bad_area;
+       if (error_code & 4) {
+               /*
+                * accessing the stack below %esp is always a bug.
+                * The "+ 32" is there due to some instructions (like
+                * pusha) doing post-decrement on the stack and that
+                * doesn't show up until later..
+                */
+               if (address + 32 < regs->esp)
+                       goto bad_area;
+       }
+       if (expand_stack(vma, address))
+               goto bad_area;
+ /*
+  * Ok, we have a good vm_area for this memory access, so
+  * we can handle it..
+  */
+ good_area:
+       info.si_code = SEGV_ACCERR;
+       write = 0;
+       switch (error_code & 3) {
+               default:        /* 3: write, present */
+ #ifdef TEST_VERIFY_AREA
+                       if (regs->cs == KERNEL_CS)
+                               printk("WP fault at %08lx\n", regs->eip);
+ #endif
+                       /* fall through */
+               case 2:         /* write, not present */
+                       if (!(vma->vm_flags & VM_WRITE))
+                               goto bad_area;
+                       write++;
+                       break;
+               case 1:         /* read, present */
+                       goto bad_area;
+               case 0:         /* read, not present */
+                       if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+                               goto bad_area;
+       }
+  survive:
+       /*
+        * If for any reason at all we couldn't handle the fault,
+        * make sure we exit gracefully rather than endlessly redo
+        * the fault.
+        */
+       switch (handle_mm_fault(mm, vma, address, write)) {
+               case VM_FAULT_MINOR:
+                       tsk->min_flt++;
+                       break;
+               case VM_FAULT_MAJOR:
+                       tsk->maj_flt++;
+                       break;
+               case VM_FAULT_SIGBUS:
+                       goto do_sigbus;
+               case VM_FAULT_OOM:
+                       goto out_of_memory;
+               default:
+                       BUG();
+       }
+       /*
+        * Did it hit the DOS screen memory VA from vm86 mode?
+        */
+       if (regs->eflags & VM_MASK) {
+               unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
+               if (bit < 32)
+                       tsk->thread.screen_bitmap |= 1 << bit;
+       }
+       up_read(&mm->mmap_sem);
+       return;
+ /*
+  * Something tried to access memory that isn't in our memory map..
+  * Fix it, but check if it's kernel or user first..
+  */
+ bad_area:
+       up_read(&mm->mmap_sem);
+ bad_area_nosemaphore:
+       /* User mode accesses just cause a SIGSEGV */
+       if (error_code & 4) {
+               /* 
+                * Valid to do another page fault here because this one came 
+                * from user space.
+                */
+               if (is_prefetch(regs, address, error_code))
+                       return;
+               tsk->thread.cr2 = address;
+               /* Kernel addresses are always protection faults */
+               tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+               tsk->thread.trap_no = 14;
+               info.si_signo = SIGSEGV;
+               info.si_errno = 0;
+               /* info.si_code has been set above */
+               info.si_addr = (void __user *)address;
+               force_sig_info(SIGSEGV, &info, tsk);
+               return;
+       }
+ #ifdef CONFIG_X86_F00F_BUG
+       /*
+        * Pentium F0 0F C7 C8 bug workaround.
+        */
+       if (boot_cpu_data.f00f_bug) {
+               unsigned long nr;
+               
+               nr = (address - idt_descr.address) >> 3;
+               if (nr == 6) {
+                       do_invalid_op(regs, 0);
+                       return;
+               }
+       }
+ #endif
+ no_context:
+       /* Are we prepared to handle this kernel fault?  */
+       if (fixup_exception(regs))
+               return;
+       /* 
+        * Valid to do another page fault here, because if this fault
+        * had been triggered by is_prefetch fixup_exception would have 
+        * handled it.
+        */
+       if (is_prefetch(regs, address, error_code))
+               return;
+ /*
+  * Oops. The kernel tried to access some bad page. We'll have to
+  * terminate things with extreme prejudice.
+  */
+       bust_spinlocks(1);
+ #ifdef CONFIG_X86_PAE
+       if (error_code & 16) {
+               pte_t *pte = lookup_address(address);
+               if (pte && pte_present(*pte) && !pte_exec_kernel(*pte))
+                       printk(KERN_CRIT "kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n", current->uid);
+       }
+ #endif
+       if (address < PAGE_SIZE)
+               printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+       else
+               printk(KERN_ALERT "Unable to handle kernel paging request");
+       printk(" at virtual address %08lx\n",address);
+       printk(KERN_ALERT " printing eip:\n");
+       printk("%08lx\n", regs->eip);
 -              pgd = index + cur_pgd;
++      page = ((unsigned long *) per_cpu(cur_pgd, smp_processor_id()))
++          [address >> 22];
+       printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page,
+              machine_to_phys(page));
+       /*
+        * We must not directly access the pte in the highpte
+        * case, the page table might be allocated in highmem.
+        * And lets rather not kmap-atomic the pte, just in case
+        * it's allocated already.
+        */
+ #ifndef CONFIG_HIGHPTE
+       if (page & 1) {
+               page &= PAGE_MASK;
+               address &= 0x003ff000;
+               page = machine_to_phys(page);
+               page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
+               printk(KERN_ALERT "*pte = ma %08lx pa %08lx\n", page,
+                      machine_to_phys(page));
+       }
+ #endif
+       show_trace(NULL, (unsigned long *)&regs[1]);
+       die("Oops", regs, error_code);
+       bust_spinlocks(0);
+       do_exit(SIGKILL);
+ /*
+  * We ran out of memory, or some other thing happened to us that made
+  * us unable to handle the page fault gracefully.
+  */
+ out_of_memory:
+       up_read(&mm->mmap_sem);
+       if (tsk->pid == 1) {
+               yield();
+               down_read(&mm->mmap_sem);
+               goto survive;
+       }
+       printk("VM: killing process %s\n", tsk->comm);
+       if (error_code & 4)
+               do_exit(SIGKILL);
+       goto no_context;
+ do_sigbus:
+       up_read(&mm->mmap_sem);
+       /* Kernel mode? Handle exceptions or die */
+       if (!(error_code & 4))
+               goto no_context;
+       /* User space => ok to do another page fault */
+       if (is_prefetch(regs, address, error_code))
+               return;
+       tsk->thread.cr2 = address;
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = 14;
+       info.si_signo = SIGBUS;
+       info.si_errno = 0;
+       info.si_code = BUS_ADRERR;
+       info.si_addr = (void __user *)address;
+       force_sig_info(SIGBUS, &info, tsk);
+       return;
+ vmalloc_fault:
+       {
+               /*
+                * Synchronize this task's top level page-table
+                * with the 'reference' page table.
+                *
+                * Do _not_ use "tsk" here. We might be inside
+                * an interrupt in the middle of a task switch..
+                */
+               int index = pgd_index(address);
+               pgd_t *pgd, *pgd_k;
+               pmd_t *pmd, *pmd_k;
+               pte_t *pte_k;
++              pgd = index + per_cpu(cur_pgd, smp_processor_id());
+               pgd_k = init_mm.pgd + index;
+               if (!pgd_present(*pgd_k))
+                       goto no_context;
+               /*
+                * set_pgd(pgd, *pgd_k); here would be useless on PAE
+                * and redundant with the set_pmd() on non-PAE.
+                */
+               pmd = pmd_offset(pgd, address);
+               pmd_k = pmd_offset(pgd_k, address);
+               if (!pmd_present(*pmd_k))
+                       goto no_context;
+               set_pmd(pmd, *pmd_k);
+               xen_flush_page_update_queue(); /* flush PMD update */
+               pte_k = pte_offset_kernel(pmd_k, address);
+               if (!pte_present(*pte_k))
+                       goto no_context;
+               return;
+       }
+ }
index 0000000000000000000000000000000000000000,81d0b8450c6a42e37f283408a01bb5ce8db00907..c6c7bafef918c6d69991b1f3c19c0cca81dbca65
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,388 +1,465 @@@
 -static mmu_update_t update_queue[QUEUE_SIZE];
 -unsigned int mmu_update_queue_idx = 0;
 -#define idx mmu_update_queue_idx
+ /******************************************************************************
+  * mm/hypervisor.c
+  * 
+  * Update page tables via the hypervisor.
+  * 
+  * Copyright (c) 2002-2004, K A Fraser
+  * 
+  * This file may be distributed separately from the Linux kernel, or
+  * incorporated into other software packages, subject to the following license:
+  * 
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+  * of this source file (the "Software"), to deal in the Software without
+  * restriction, including without limitation the rights to use, copy, modify,
+  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  * and to permit persons to whom the Software is furnished to do so, subject to
+  * the following conditions:
+  * 
+  * The above copyright notice and this permission notice shall be included in
+  * all copies or substantial portions of the Software.
+  * 
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  * IN THE SOFTWARE.
+  */
+ #include <linux/config.h>
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+ #include <linux/vmalloc.h>
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
+ #include <asm-xen/hypervisor.h>
+ #include <asm-xen/multicall.h>
+ #include <asm-xen/balloon.h>
++#include <linux/percpu.h>
+ /*
+  * This suffices to protect us if we ever move to SMP domains.
+  * Further, it protects us against interrupts. At the very least, this is
+  * required for the network driver which flushes the update queue before
+  * pushing new receive buffers.
+  */
+ static spinlock_t update_lock = SPIN_LOCK_UNLOCKED;
+ /* Linux 2.6 isn't using the traditional batched interface. */
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ #define QUEUE_SIZE 2048
+ #define pte_offset_kernel pte_offset
+ #else
++#ifdef CONFIG_SMP
++#define QUEUE_SIZE 1
++#else
+ #define QUEUE_SIZE 128
+ #endif
++#endif
 -        idx = 0;
++DEFINE_PER_CPU(mmu_update_t, update_queue[QUEUE_SIZE]);
++DEFINE_PER_CPU(unsigned int, mmu_update_queue_idx);
+ /*
+  * MULTICALL_flush_page_update_queue:
+  *   This is a version of the flush which queues as part of a multicall.
+  */
+ void MULTICALL_flush_page_update_queue(void)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     unsigned int _idx;
+     spin_lock_irqsave(&update_lock, flags);
++    idx = per_cpu(mmu_update_queue_idx, cpu);
+     if ( (_idx = idx) != 0 ) 
+     {
 -                         (unsigned long)update_queue, 
++        per_cpu(mmu_update_queue_idx, cpu) = 0;
+         wmb(); /* Make sure index is cleared first to avoid double updates. */
+         queue_multicall3(__HYPERVISOR_mmu_update, 
 -    unsigned int _idx = idx;
 -    idx = 0;
++                         (unsigned long)&per_cpu(update_queue[0], cpu), 
+                          (unsigned long)_idx, 
+                          (unsigned long)NULL);
+     }
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ static inline void __flush_page_update_queue(void)
+ {
 -    if ( unlikely(HYPERVISOR_mmu_update(update_queue, _idx, NULL) < 0) )
++    int cpu = smp_processor_id();
++    unsigned int _idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(mmu_update_queue_idx, cpu) = 0;
+     wmb(); /* Make sure index is cleared first to avoid double updates. */
 -    if ( idx != 0 ) __flush_page_update_queue();
++    if ( unlikely(HYPERVISOR_mmu_update(&per_cpu(update_queue[0], cpu), _idx, NULL) < 0) )
+     {
+         printk(KERN_ALERT "Failed to execute MMU updates.\n");
+         BUG();
+     }
+ }
+ void _flush_page_update_queue(void)
+ {
++    int cpu = smp_processor_id();
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    idx++;
 -    if ( unlikely(idx == QUEUE_SIZE) ) __flush_page_update_queue();
++    if ( per_cpu(mmu_update_queue_idx, cpu) != 0 ) __flush_page_update_queue();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ static inline void increment_index(void)
+ {
 -    idx++;
++    int cpu = smp_processor_id();
++    per_cpu(mmu_update_queue_idx, cpu)++;
++    if ( unlikely(per_cpu(mmu_update_queue_idx, cpu) == QUEUE_SIZE) ) __flush_page_update_queue();
+ }
+ static inline void increment_index_and_flush(void)
+ {
 -    update_queue[idx].ptr = virt_to_machine(ptr);
 -    update_queue[idx].val = val;
++    int cpu = smp_processor_id();
++    per_cpu(mmu_update_queue_idx, cpu)++;
+     __flush_page_update_queue();
+ }
+ void queue_l1_entry_update(pte_t *ptr, unsigned long val)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr = virt_to_machine(ptr);
 -    update_queue[idx].val = val;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr = virt_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).val = val;
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void queue_l2_entry_update(pmd_t *ptr, unsigned long val)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = phys_to_machine(ptr);
 -    update_queue[idx].ptr |= MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_NEW_BASEPTR;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr = virt_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).val = val;
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void queue_pt_switch(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_TLB_FLUSH;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = phys_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).ptr |= MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_NEW_BASEPTR;
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void queue_tlb_flush(void)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = MMU_EXTENDED_COMMAND;
 -    update_queue[idx].ptr |= ptr & PAGE_MASK;
 -    update_queue[idx].val  = MMUEXT_INVLPG;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_TLB_FLUSH;
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void queue_invlpg(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = phys_to_machine(ptr);
 -    update_queue[idx].ptr |= MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_PIN_L2_TABLE;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).ptr |= ptr & PAGE_MASK;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_INVLPG;
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void queue_pgd_pin(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = phys_to_machine(ptr);
 -    update_queue[idx].ptr |= MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_UNPIN_TABLE;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = phys_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).ptr |= MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_PIN_L2_TABLE;
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void queue_pgd_unpin(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = phys_to_machine(ptr);
 -    update_queue[idx].ptr |= MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_PIN_L1_TABLE;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = phys_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).ptr |= MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_UNPIN_TABLE;
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void queue_pte_pin(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = phys_to_machine(ptr);
 -    update_queue[idx].ptr |= MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_UNPIN_TABLE;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = phys_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).ptr |= MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_PIN_L1_TABLE;
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void queue_pte_unpin(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = MMU_EXTENDED_COMMAND | ptr;
 -    update_queue[idx].val  = MMUEXT_SET_LDT | (len << MMUEXT_CMD_SHIFT);
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = phys_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).ptr |= MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_UNPIN_TABLE;
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void queue_set_ldt(unsigned long ptr, unsigned long len)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr = (mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
 -    update_queue[idx].val = pfn;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = MMU_EXTENDED_COMMAND | ptr;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_SET_LDT | (len << MMUEXT_CMD_SHIFT);
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void queue_machphys_update(unsigned long mfn, unsigned long pfn)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr = virt_to_machine(ptr);
 -    update_queue[idx].val = val;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr = (mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
++    per_cpu(update_queue[idx], cpu).val = pfn;
+     increment_index();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ /* queue and flush versions of the above */
+ void xen_l1_entry_update(pte_t *ptr, unsigned long val)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr = virt_to_machine(ptr);
 -    update_queue[idx].val = val;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr = virt_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).val = val;
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void xen_l2_entry_update(pmd_t *ptr, unsigned long val)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = phys_to_machine(ptr);
 -    update_queue[idx].ptr |= MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_NEW_BASEPTR;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr = virt_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).val = val;
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void xen_pt_switch(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_TLB_FLUSH;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = phys_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).ptr |= MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_NEW_BASEPTR;
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void xen_tlb_flush(void)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = MMU_EXTENDED_COMMAND;
 -    update_queue[idx].ptr |= ptr & PAGE_MASK;
 -    update_queue[idx].val  = MMUEXT_INVLPG;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_TLB_FLUSH;
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void xen_invlpg(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = phys_to_machine(ptr);
 -    update_queue[idx].ptr |= MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_PIN_L2_TABLE;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).ptr |= ptr & PAGE_MASK;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_INVLPG;
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void xen_pgd_pin(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = phys_to_machine(ptr);
 -    update_queue[idx].ptr |= MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_UNPIN_TABLE;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = phys_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).ptr |= MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_PIN_L2_TABLE;
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void xen_pgd_unpin(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = phys_to_machine(ptr);
 -    update_queue[idx].ptr |= MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_PIN_L1_TABLE;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = phys_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).ptr |= MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_UNPIN_TABLE;
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void xen_pte_pin(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = phys_to_machine(ptr);
 -    update_queue[idx].ptr |= MMU_EXTENDED_COMMAND;
 -    update_queue[idx].val  = MMUEXT_UNPIN_TABLE;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = phys_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).ptr |= MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_PIN_L1_TABLE;
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void xen_pte_unpin(unsigned long ptr)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr  = MMU_EXTENDED_COMMAND | ptr;
 -    update_queue[idx].val  = MMUEXT_SET_LDT | (len << MMUEXT_CMD_SHIFT);
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = phys_to_machine(ptr);
++    per_cpu(update_queue[idx], cpu).ptr |= MMU_EXTENDED_COMMAND;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_UNPIN_TABLE;
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void xen_set_ldt(unsigned long ptr, unsigned long len)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
 -    update_queue[idx].ptr = (mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
 -    update_queue[idx].val = pfn;
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr  = MMU_EXTENDED_COMMAND | ptr;
++    per_cpu(update_queue[idx], cpu).val  = MMUEXT_SET_LDT | (len << MMUEXT_CMD_SHIFT);
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ void xen_machphys_update(unsigned long mfn, unsigned long pfn)
+ {
++    int cpu = smp_processor_id();
++    int idx;
+     unsigned long flags;
+     spin_lock_irqsave(&update_lock, flags);
++    idx = per_cpu(mmu_update_queue_idx, cpu);
++    per_cpu(update_queue[idx], cpu).ptr = (mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
++    per_cpu(update_queue[idx], cpu).val = pfn;
+     increment_index_and_flush();
+     spin_unlock_irqrestore(&update_lock, flags);
+ }
+ #ifdef CONFIG_XEN_PHYSDEV_ACCESS
+ unsigned long allocate_empty_lowmem_region(unsigned long pages)
+ {
+     pgd_t         *pgd; 
+     pmd_t         *pmd;
+     pte_t         *pte;
+     unsigned long *pfn_array;
+     unsigned long  vstart;
+     unsigned long  i;
+     unsigned int   order = get_order(pages*PAGE_SIZE);
+     vstart = __get_free_pages(GFP_KERNEL, order);
+     if ( vstart == 0 )
+         return 0UL;
+     scrub_pages(vstart, 1 << order);
+     pfn_array = vmalloc((1<<order) * sizeof(*pfn_array));
+     if ( pfn_array == NULL )
+         BUG();
+     for ( i = 0; i < (1<<order); i++ )
+     {
+         pgd = pgd_offset_k(   (vstart + (i*PAGE_SIZE)));
+         pmd = pmd_offset(pgd, (vstart + (i*PAGE_SIZE)));
+         pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE))); 
+         pfn_array[i] = pte->pte_low >> PAGE_SHIFT;
+         queue_l1_entry_update(pte, 0);
+         phys_to_machine_mapping[__pa(vstart)>>PAGE_SHIFT] = INVALID_P2M_ENTRY;
+     }
+     /* Flush updates through and flush the TLB. */
+     xen_tlb_flush();
+     balloon_put_pages(pfn_array, 1 << order);
+     vfree(pfn_array);
+     return vstart;
+ }
+ #endif /* CONFIG_XEN_PHYSDEV_ACCESS */
index 0000000000000000000000000000000000000000,4b74f30cb62c32ccf25bb73194fe05bd7e3ce48b..cce08650737a18a15da7e0213c12bca17bf0938e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,14 +1,15 @@@
 -obj-y := ctrl_if.o evtchn.o fixup.o reboot.o xen_proc.o gnttab.o skbuff.o devmem.o
+ #
+ # Makefile for the linux kernel.
+ #
+ XENARCH       := $(subst ",,$(CONFIG_XENARCH))
+ CPPFLAGS_vmlinux.lds += -U$(XENARCH)
+ $(obj)/vmlinux.lds.S:
+       @ln -fsn $(srctree)/arch/$(XENARCH)/kernel/vmlinux.lds.S $@
+ extra-y += vmlinux.lds
++obj-y := ctrl_if.o evtchn.o fixup.o reboot.o xen_proc.o \
++           gnttab.o skbuff.o devmem.o smp.o
index 0000000000000000000000000000000000000000,e5aa5a1b183971f1f35a62252d1e494d23327b05..f1a3b178872a6f30d862eac12a00b9372cc3949a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,541 +1,593 @@@
 -static int virq_to_irq[NR_VIRQS];
+ /******************************************************************************
+  * evtchn.c
+  * 
+  * Communication via Xen event channels.
+  * 
+  * Copyright (c) 2002-2004, K A Fraser
+  * 
+  * This file may be distributed separately from the Linux kernel, or
+  * incorporated into other software packages, subject to the following license:
+  * 
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+  * of this source file (the "Software"), to deal in the Software without
+  * restriction, including without limitation the rights to use, copy, modify,
+  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  * and to permit persons to whom the Software is furnished to do so, subject to
+  * the following conditions:
+  * 
+  * The above copyright notice and this permission notice shall be included in
+  * all copies or substantial portions of the Software.
+  * 
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  * IN THE SOFTWARE.
+  */
+ #include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/irq.h>
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/version.h>
+ #include <asm/atomic.h>
+ #include <asm/system.h>
+ #include <asm/ptrace.h>
+ #include <asm/synch_bitops.h>
+ #include <asm-xen/xen-public/event_channel.h>
+ #include <asm-xen/xen-public/physdev.h>
+ #include <asm-xen/ctrl_if.h>
+ #include <asm-xen/hypervisor.h>
++#define XEN_EVTCHN_MASK_OPS
++#include <asm-xen/evtchn.h>
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ EXPORT_SYMBOL(force_evtchn_callback);
+ EXPORT_SYMBOL(evtchn_do_upcall);
+ #endif
+ /*
+  * This lock protects updates to the following mapping and reference-count
+  * arrays. The lock does not need to be acquired to read the mapping tables.
+  */
+ static spinlock_t irq_mapping_update_lock;
+ /* IRQ <-> event-channel mappings. */
+ static int evtchn_to_irq[NR_EVENT_CHANNELS];
+ static int irq_to_evtchn[NR_IRQS];
+ /* IRQ <-> VIRQ mapping. */
 -    while ( s->vcpu_data[0].evtchn_upcall_pending )
++DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]);
++
++/* evtchn <-> IPI mapping. */
++DEFINE_PER_CPU(int, ipi_to_evtchn[NR_IPIS]);
+ /* Reference counts for bindings to IRQs. */
+ static int irq_bindcount[NR_IRQS];
+ /* Bitmap indicating which PIRQs require Xen to be notified on unmask. */
+ static unsigned long pirq_needs_unmask_notify[NR_PIRQS/sizeof(unsigned long)];
+ /* Upcall to generic IRQ layer. */
+ #ifdef CONFIG_X86
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
+ extern fastcall unsigned int do_IRQ(struct pt_regs *regs);
+ #else
+ extern asmlinkage unsigned int do_IRQ(struct pt_regs *regs);
+ #endif
+ #define do_IRQ(irq, regs) do {                \
+     (regs)->orig_eax = (irq);         \
+     do_IRQ((regs));                   \
+ } while (0)
+ #endif
+ #define VALID_EVTCHN(_chn) ((_chn) >= 0)
+ /*
+  * Force a proper event-channel callback from Xen after clearing the
+  * callback mask. We do this in a very simple manner, by making a call
+  * down into Xen. The pending flag will be checked by Xen on return.
+  */
+ void force_evtchn_callback(void)
+ {
+     (void)HYPERVISOR_xen_version(0);
+ }
+ asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
+ {
+     unsigned long  l1, l2;
+     unsigned int   l1i, l2i, port;
+     int            irq;
+     unsigned long  flags;
+     shared_info_t *s = HYPERVISOR_shared_info;
++    vcpu_info_t   *vcpu_info = &s->vcpu_data[smp_processor_id()];
+     local_irq_save(flags);
+     
 -        s->vcpu_data[0].evtchn_upcall_pending = 0;
++    while ( vcpu_info->evtchn_upcall_pending )
+     {
 -        l1 = xchg(&s->evtchn_pending_sel, 0);
++        vcpu_info->evtchn_upcall_pending = 0;
+         /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
 -            l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
 -            while ( (l2i = ffs(l2)) != 0 )
++        l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
+         while ( (l1i = ffs(l1)) != 0 )
+         {
+             l1i--;
+             l1 &= ~(1 << l1i);
+         
 -    if ( (irq = virq_to_irq[virq]) == -1 )
++            for ( ;; )
+             {
++                l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
++                l2i = ffs(l2);
++                if ( l2i == 0 )
++                    break;
+                 l2i--;
+                 l2 &= ~(1 << l2i);
+             
+                 port = (l1i << 5) + l2i;
+                 if ( (irq = evtchn_to_irq[port]) != -1 )
+                     do_IRQ(irq, regs);
+                 else
+                     evtchn_device_upcall(port);
+             }
+         }
+     }
+     local_irq_restore(flags);
+ }
+ static int find_unbound_irq(void)
+ {
+     int irq;
+     for ( irq = 0; irq < NR_IRQS; irq++ )
+         if ( irq_bindcount[irq] == 0 )
+             break;
+     if ( irq == NR_IRQS )
+         panic("No available IRQ to bind to: increase NR_IRQS!\n");
+     return irq;
+ }
+ int bind_virq_to_irq(int virq)
+ {
+     evtchn_op_t op;
+     int evtchn, irq;
++    int cpu = smp_processor_id();
+     spin_lock(&irq_mapping_update_lock);
 -        virq_to_irq[virq] = irq;
++    if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 )
+     {
+         op.cmd              = EVTCHNOP_bind_virq;
+         op.u.bind_virq.virq = virq;
+         if ( HYPERVISOR_event_channel_op(&op) != 0 )
+             panic("Failed to bind virtual IRQ %d\n", virq);
+         evtchn = op.u.bind_virq.port;
+         irq = find_unbound_irq();
+         evtchn_to_irq[evtchn] = irq;
+         irq_to_evtchn[irq]    = evtchn;
 -    int irq    = virq_to_irq[virq];
++        per_cpu(virq_to_irq, cpu)[virq] = irq;
+     }
+     irq_bindcount[irq]++;
+     spin_unlock(&irq_mapping_update_lock);
+     
+     return irq;
+ }
+ void unbind_virq_from_irq(int virq)
+ {
+     evtchn_op_t op;
 -        virq_to_irq[virq]     = -1;
++    int cpu    = smp_processor_id();
++    int irq    = per_cpu(virq_to_irq, cpu)[virq];
+     int evtchn = irq_to_evtchn[irq];
+     spin_lock(&irq_mapping_update_lock);
+     if ( --irq_bindcount[irq] == 0 )
+     {
+         op.cmd          = EVTCHNOP_close;
+         op.u.close.dom  = DOMID_SELF;
+         op.u.close.port = evtchn;
+         if ( HYPERVISOR_event_channel_op(&op) != 0 )
+             panic("Failed to unbind virtual IRQ %d\n", virq);
+         evtchn_to_irq[evtchn] = -1;
+         irq_to_evtchn[irq]    = -1;
 -static irqreturn_t misdirect_interrupt(int irq, void *dev_id,
 -                                       struct pt_regs *regs)
 -{
 -    /* nothing */
 -    return IRQ_HANDLED;
 -}
 -
 -static struct irqaction misdirect_action = {
 -    misdirect_interrupt, 
 -    SA_INTERRUPT, 
 -    CPU_MASK_NONE, 
 -    "misdirect", 
 -    NULL, 
 -    NULL
 -};
 -
++        per_cpu(virq_to_irq, cpu)[virq]     = -1;
++    }
++
++    spin_unlock(&irq_mapping_update_lock);
++}
++
++int bind_ipi_on_cpu_to_irq(int cpu, int ipi)
++{
++    evtchn_op_t op;
++    int evtchn, irq;
++
++    spin_lock(&irq_mapping_update_lock);
++
++    if ( (evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == 0 )
++    {
++        op.cmd                 = EVTCHNOP_bind_ipi;
++        op.u.bind_ipi.ipi_edom = cpu;
++        if ( HYPERVISOR_event_channel_op(&op) != 0 )
++            panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, cpu);
++        evtchn = op.u.bind_ipi.port;
++
++        irq = find_unbound_irq();
++        evtchn_to_irq[evtchn] = irq;
++        irq_to_evtchn[irq]    = evtchn;
++
++        per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn;
++    } else
++      irq = evtchn_to_irq[evtchn];
++
++    irq_bindcount[irq]++;
++
++    spin_unlock(&irq_mapping_update_lock);
++
++    return irq;
++}
++
++void unbind_ipi_on_cpu_from_irq(int cpu, int ipi)
++{
++    evtchn_op_t op;
++    int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
++    int irq    = irq_to_evtchn[evtchn];
++
++    spin_lock(&irq_mapping_update_lock);
++
++    if ( --irq_bindcount[irq] == 0 )
++    {
++      op.cmd          = EVTCHNOP_close;
++      op.u.close.dom  = DOMID_SELF;
++      op.u.close.port = evtchn;
++      if ( HYPERVISOR_event_channel_op(&op) != 0 )
++          panic("Failed to unbind virtual IPI %d on cpu %d\n", ipi, cpu);
++
++        evtchn_to_irq[evtchn] = -1;
++        irq_to_evtchn[irq]    = -1;
++      per_cpu(ipi_to_evtchn, cpu)[ipi] = 0;
+     }
+     spin_unlock(&irq_mapping_update_lock);
+ }
+ int bind_evtchn_to_irq(int evtchn)
+ {
+     int irq;
+     spin_lock(&irq_mapping_update_lock);
+     if ( (irq = evtchn_to_irq[evtchn]) == -1 )
+     {
+         irq = find_unbound_irq();
+         evtchn_to_irq[evtchn] = irq;
+         irq_to_evtchn[irq]    = evtchn;
+     }
+     irq_bindcount[irq]++;
+     spin_unlock(&irq_mapping_update_lock);
+     
+     return irq;
+ }
+ void unbind_evtchn_from_irq(int evtchn)
+ {
+     int irq = evtchn_to_irq[evtchn];
+     spin_lock(&irq_mapping_update_lock);
+     if ( --irq_bindcount[irq] == 0 )
+     {
+         evtchn_to_irq[evtchn] = -1;
+         irq_to_evtchn[irq]    = -1;
+     }
+     spin_unlock(&irq_mapping_update_lock);
+ }
+ /*
+  * Interface to generic handling in irq.c
+  */
+ static unsigned int startup_dynirq(unsigned int irq)
+ {
+     int evtchn = irq_to_evtchn[irq];
+     if ( !VALID_EVTCHN(evtchn) )
+         return 0;
+     unmask_evtchn(evtchn);
+     return 0;
+ }
+ static void shutdown_dynirq(unsigned int irq)
+ {
+     int evtchn = irq_to_evtchn[irq];
+     if ( !VALID_EVTCHN(evtchn) )
+         return;
+     mask_evtchn(evtchn);
+ }
+ static void enable_dynirq(unsigned int irq)
+ {
+     int evtchn = irq_to_evtchn[irq];
+     unmask_evtchn(evtchn);
+ }
+ static void disable_dynirq(unsigned int irq)
+ {
+     int evtchn = irq_to_evtchn[irq];
+     mask_evtchn(evtchn);
+ }
+ static void ack_dynirq(unsigned int irq)
+ {
+     int evtchn = irq_to_evtchn[irq];
+     mask_evtchn(evtchn);
+     clear_evtchn(evtchn);
+ }
+ static void end_dynirq(unsigned int irq)
+ {
+     int evtchn = irq_to_evtchn[irq];
+     if ( !(irq_desc[irq].status & IRQ_DISABLED) )
+         unmask_evtchn(evtchn);
+ }
+ static struct hw_interrupt_type dynirq_type = {
+     "Dynamic-irq",
+     startup_dynirq,
+     shutdown_dynirq,
+     enable_dynirq,
+     disable_dynirq,
+     ack_dynirq,
+     end_dynirq,
+     NULL
+ };
+ static inline void pirq_unmask_notify(int pirq)
+ {
+     physdev_op_t op;
+     if ( unlikely(test_bit(pirq, &pirq_needs_unmask_notify[0])) )
+     {
+         op.cmd = PHYSDEVOP_IRQ_UNMASK_NOTIFY;
+         (void)HYPERVISOR_physdev_op(&op);
+     }
+ }
+ static inline void pirq_query_unmask(int pirq)
+ {
+     physdev_op_t op;
+     op.cmd = PHYSDEVOP_IRQ_STATUS_QUERY;
+     op.u.irq_status_query.irq = pirq;
+     (void)HYPERVISOR_physdev_op(&op);
+     clear_bit(pirq, &pirq_needs_unmask_notify[0]);
+     if ( op.u.irq_status_query.flags & PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY )
+         set_bit(pirq, &pirq_needs_unmask_notify[0]);
+ }
+ /*
+  * On startup, if there is no action associated with the IRQ then we are
+  * probing. In this case we should not share with others as it will confuse us.
+  */
+ #define probing_irq(_irq) (irq_desc[(_irq)].action == NULL)
+ static unsigned int startup_pirq(unsigned int irq)
+ {
+     evtchn_op_t op;
+     int evtchn;
+     op.cmd               = EVTCHNOP_bind_pirq;
+     op.u.bind_pirq.pirq  = irq;
+     /* NB. We are happy to share unless we are probing. */
+     op.u.bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE;
+     if ( HYPERVISOR_event_channel_op(&op) != 0 )
+     {
+         if ( !probing_irq(irq) ) /* Some failures are expected when probing. */
+             printk(KERN_INFO "Failed to obtain physical IRQ %d\n", irq);
+         return 0;
+     }
+     evtchn = op.u.bind_pirq.port;
+     pirq_query_unmask(irq_to_pirq(irq));
+     evtchn_to_irq[evtchn] = irq;
+     irq_to_evtchn[irq]    = evtchn;
+     unmask_evtchn(evtchn);
+     pirq_unmask_notify(irq_to_pirq(irq));
+     return 0;
+ }
+ static void shutdown_pirq(unsigned int irq)
+ {
+     evtchn_op_t op;
+     int evtchn = irq_to_evtchn[irq];
+     if ( !VALID_EVTCHN(evtchn) )
+         return;
+     mask_evtchn(evtchn);
+     op.cmd          = EVTCHNOP_close;
+     op.u.close.dom  = DOMID_SELF;
+     op.u.close.port = evtchn;
+     if ( HYPERVISOR_event_channel_op(&op) != 0 )
+         panic("Failed to unbind physical IRQ %d\n", irq);
+     evtchn_to_irq[evtchn] = -1;
+     irq_to_evtchn[irq]    = -1;
+ }
+ static void enable_pirq(unsigned int irq)
+ {
+     int evtchn = irq_to_evtchn[irq];
+     if ( !VALID_EVTCHN(evtchn) )
+         return;
+     unmask_evtchn(evtchn);
+     pirq_unmask_notify(irq_to_pirq(irq));
+ }
+ static void disable_pirq(unsigned int irq)
+ {
+     int evtchn = irq_to_evtchn[irq];
+     if ( !VALID_EVTCHN(evtchn) )
+         return;
+     mask_evtchn(evtchn);
+ }
+ static void ack_pirq(unsigned int irq)
+ {
+     int evtchn = irq_to_evtchn[irq];
+     if ( !VALID_EVTCHN(evtchn) )
+         return;
+     mask_evtchn(evtchn);
+     clear_evtchn(evtchn);
+ }
+ static void end_pirq(unsigned int irq)
+ {
+     int evtchn = irq_to_evtchn[irq];
+     if ( !VALID_EVTCHN(evtchn) )
+         return;
+     if ( !(irq_desc[irq].status & IRQ_DISABLED) )
+     {
+         unmask_evtchn(evtchn);
+         pirq_unmask_notify(irq_to_pirq(irq));
+     }
+ }
+ static struct hw_interrupt_type pirq_type = {
+     "Phys-irq",
+     startup_pirq,
+     shutdown_pirq,
+     enable_pirq,
+     disable_pirq,
+     ack_pirq,
+     end_pirq,
+     NULL
+ };
 -        if ( (irq = virq_to_irq[virq]) == -1 )
+ void irq_suspend(void)
+ {
+     int pirq, virq, irq, evtchn;
++    int cpu = smp_processor_id(); /* XXX */
+     /* Unbind VIRQs from event channels. */
+     for ( virq = 0; virq < NR_VIRQS; virq++ )
+     {
 -        if ( (irq = virq_to_irq[virq]) == -1 )
++        if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 )
+             continue;
+         evtchn = irq_to_evtchn[irq];
+         /* Mark the event channel as unused in our table. */
+         evtchn_to_irq[evtchn] = -1;
+         irq_to_evtchn[irq]    = -1;
+     }
+     /* Check that no PIRQs are still bound. */
+     for ( pirq = 0; pirq < NR_PIRQS; pirq++ )
+         if ( (evtchn = irq_to_evtchn[pirq_to_irq(pirq)]) != -1 )
+             panic("Suspend attempted while PIRQ %d bound to evtchn %d.\n",
+                   pirq, evtchn);
+ }
+ void irq_resume(void)
+ {
+     evtchn_op_t op;
+     int         virq, irq, evtchn;
++    int cpu = smp_processor_id(); /* XXX */
+     for ( evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++ )
+         mask_evtchn(evtchn); /* New event-channel space is not 'live' yet. */
+     for ( virq = 0; virq < NR_VIRQS; virq++ )
+     {
 -    /* No VIRQ -> IRQ mappings. */
 -    for ( i = 0; i < NR_VIRQS; i++ )
 -        virq_to_irq[i] = -1;
++        if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 )
+             continue;
+         /* Get a new binding from Xen. */
+         op.cmd              = EVTCHNOP_bind_virq;
+         op.u.bind_virq.virq = virq;
+         if ( HYPERVISOR_event_channel_op(&op) != 0 )
+             panic("Failed to bind virtual IRQ %d\n", virq);
+         evtchn = op.u.bind_virq.port;
+         
+         /* Record the new mapping. */
+         evtchn_to_irq[evtchn] = irq;
+         irq_to_evtchn[irq]    = evtchn;
+         /* Ready for use. */
+         unmask_evtchn(evtchn);
+     }
+ }
+ void __init init_IRQ(void)
+ {
+     int i;
++    int cpu;
+     irq_ctx_init(0);
+     spin_lock_init(&irq_mapping_update_lock);
 -    (void)setup_irq(bind_virq_to_irq(VIRQ_MISDIRECT), &misdirect_action);
 -
++    for ( cpu = 0; cpu < NR_CPUS; cpu++ ) {
++      /* No VIRQ -> IRQ mappings. */
++      for ( i = 0; i < NR_VIRQS; i++ )
++          per_cpu(virq_to_irq, cpu)[i] = -1;
++    }
+     /* No event-channel -> IRQ mappings. */
+     for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
+     {
+         evtchn_to_irq[i] = -1;
+         mask_evtchn(i); /* No event channels are 'live' right now. */
+     }
+     /* No IRQ -> event-channel mappings. */
+     for ( i = 0; i < NR_IRQS; i++ )
+         irq_to_evtchn[i] = -1;
+     for ( i = 0; i < NR_DYNIRQS; i++ )
+     {
+         /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
+         irq_bindcount[dynirq_to_irq(i)] = 0;
+         irq_desc[dynirq_to_irq(i)].status  = IRQ_DISABLED;
+         irq_desc[dynirq_to_irq(i)].action  = 0;
+         irq_desc[dynirq_to_irq(i)].depth   = 1;
+         irq_desc[dynirq_to_irq(i)].handler = &dynirq_type;
+     }
+     for ( i = 0; i < NR_PIRQS; i++ )
+     {
+         /* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */
+         irq_bindcount[pirq_to_irq(i)] = 1;
+         irq_desc[pirq_to_irq(i)].status  = IRQ_DISABLED;
+         irq_desc[pirq_to_irq(i)].action  = 0;
+         irq_desc[pirq_to_irq(i)].depth   = 1;
+         irq_desc[pirq_to_irq(i)].handler = &pirq_type;
+     }
+     /* This needs to be done early, but after the IRQ subsystem is alive. */
+     ctrl_if_init();
+ }
index 0000000000000000000000000000000000000000,0bfb5a50c39ca7ae74d133adb535ac24ad1aef63..7bb47983097349baf5728a4abfbfe746986860da
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,12 +1,13 @@@
+ obj-y += console/
+ obj-y += evtchn/
+ obj-y += balloon/
+ obj-$(CONFIG_XEN_PRIVILEGED_GUEST)    += privcmd/
+ obj-$(CONFIG_XEN_BLKDEV_BACKEND)      += blkback/
+ obj-$(CONFIG_XEN_NETDEV_BACKEND)      += netback/
+ obj-$(CONFIG_XEN_BLKDEV_FRONTEND)     += blkfront/
+ obj-$(CONFIG_XEN_NETDEV_FRONTEND)     += netfront/
++obj-$(CONFIG_XEN_BLKDEV_TAP)          += blktap/
index 0000000000000000000000000000000000000000,6d201022d25269929e6d27bcff39e43fe664a1d2..b3d195cb0db841e7dff444a7efd3aaf6491646cb
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,586 +1,621 @@@
 -        0, blkif->domid) )
+ /******************************************************************************
+  * arch/xen/drivers/blkif/backend/main.c
+  * 
+  * Back-end of the driver for virtual block devices. This portion of the
+  * driver exports a 'unified' block-device interface that can be accessed
+  * by any operating system that implements a compatible front end. A 
+  * reference front-end implementation can be found in:
+  *  arch/xen/drivers/blkif/frontend
+  * 
+  * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+  */
+ #include "common.h"
++#include <asm-xen/evtchn.h>
+ /*
+  * These are rather arbitrary. They are fairly large because adjacent requests
+  * pulled from a communication ring are quite likely to end up being part of
+  * the same scatter/gather request at the disc.
+  * 
+  * ** TRY INCREASING 'MAX_PENDING_REQS' IF WRITE SPEEDS SEEM TOO LOW **
+  * This will increase the chances of being able to write whole tracks.
+  * 64 should be enough to keep us competitive with Linux.
+  */
+ #define MAX_PENDING_REQS 64
+ #define BATCH_PER_DOMAIN 16
+ static unsigned long mmap_vstart;
+ #define MMAP_PAGES_PER_REQUEST \
+     (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1)
+ #define MMAP_PAGES             \
+     (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
+ #define MMAP_VADDR(_req,_seg)                        \
+     (mmap_vstart +                                   \
+      ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
+      ((_seg) * PAGE_SIZE))
+ /*
+  * Each outstanding request that we've passed to the lower device layers has a 
+  * 'pending_req' allocated to it. Each buffer_head that completes decrements 
+  * the pendcnt towards zero. When it hits zero, the specified domain has a 
+  * response queued for it, with the saved 'id' passed back.
+  */
+ typedef struct {
+     blkif_t       *blkif;
+     unsigned long  id;
+     int            nr_pages;
+     atomic_t       pendcnt;
+     unsigned short operation;
+     int            status;
+ } pending_req_t;
+ /*
+  * We can't allocate pending_req's in order, since they may complete out of 
+  * order. We therefore maintain an allocation ring. This ring also indicates 
+  * when enough work has been passed down -- at that point the allocation ring 
+  * will be empty.
+  */
+ static pending_req_t pending_reqs[MAX_PENDING_REQS];
+ static unsigned char pending_ring[MAX_PENDING_REQS];
+ static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED;
+ /* NB. We use a different index type to differentiate from shared blk rings. */
+ typedef unsigned int PEND_RING_IDX;
+ #define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
+ static PEND_RING_IDX pending_prod, pending_cons;
+ #define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ static kmem_cache_t *buffer_head_cachep;
+ #endif
++#ifdef CONFIG_XEN_BLKDEV_TAP_BE
++/*
++ * If the tap driver is used, we may get pages belonging to either the tap
++ * or (more likely) the real frontend.  The backend must specify which domain
++ * a given page belongs to in update_va_mapping though.  For the moment, 
++ * we pass in the domid of the real frontend in PROBE messages and store 
++ * this value in alt_dom.  Then on mapping, we try both.  This is a Guiness 
++ * book of records-calibre grim hack, and represents a bit of a security risk.
++ * Grant tables will soon solve the problem though!
++ */
++static domid_t alt_dom = 0;
++#endif
++
+ static int do_block_io_op(blkif_t *blkif, int max_to_do);
+ static void dispatch_probe(blkif_t *blkif, blkif_request_t *req);
+ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req);
+ static void make_response(blkif_t *blkif, unsigned long id, 
+                           unsigned short op, int st);
+ static void fast_flush_area(int idx, int nr_pages)
+ {
+     multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
+     int               i;
+     for ( i = 0; i < nr_pages; i++ )
+     {
+         mcl[i].op = __HYPERVISOR_update_va_mapping;
+         mcl[i].args[0] = MMAP_VADDR(idx, i) >> PAGE_SHIFT;
+         mcl[i].args[1] = 0;
+         mcl[i].args[2] = 0;
+     }
+     mcl[nr_pages-1].args[2] = UVMF_FLUSH_TLB;
+     if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) )
+         BUG();
+ }
+ /******************************************************************
+  * BLOCK-DEVICE SCHEDULER LIST MAINTENANCE
+  */
+ static struct list_head blkio_schedule_list;
+ static spinlock_t blkio_schedule_list_lock;
+ static int __on_blkdev_list(blkif_t *blkif)
+ {
+     return blkif->blkdev_list.next != NULL;
+ }
+ static void remove_from_blkdev_list(blkif_t *blkif)
+ {
+     unsigned long flags;
+     if ( !__on_blkdev_list(blkif) ) return;
+     spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+     if ( __on_blkdev_list(blkif) )
+     {
+         list_del(&blkif->blkdev_list);
+         blkif->blkdev_list.next = NULL;
+         blkif_put(blkif);
+     }
+     spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+ }
+ static void add_to_blkdev_list_tail(blkif_t *blkif)
+ {
+     unsigned long flags;
+     if ( __on_blkdev_list(blkif) ) return;
+     spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+     if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
+     {
+         list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
+         blkif_get(blkif);
+     }
+     spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+ }
+ /******************************************************************
+  * SCHEDULER FUNCTIONS
+  */
+ static DECLARE_WAIT_QUEUE_HEAD(blkio_schedule_wait);
+ static int blkio_schedule(void *arg)
+ {
+     DECLARE_WAITQUEUE(wq, current);
+     blkif_t          *blkif;
+     struct list_head *ent;
+     daemonize(
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+         "xenblkd"
+ #endif
+         );
+     for ( ; ; )
+     {
+         /* Wait for work to do. */
+         add_wait_queue(&blkio_schedule_wait, &wq);
+         set_current_state(TASK_INTERRUPTIBLE);
+         if ( (NR_PENDING_REQS == MAX_PENDING_REQS) || 
+              list_empty(&blkio_schedule_list) )
+             schedule();
+         __set_current_state(TASK_RUNNING);
+         remove_wait_queue(&blkio_schedule_wait, &wq);
+         /* Queue up a batch of requests. */
+         while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
+                 !list_empty(&blkio_schedule_list) )
+         {
+             ent = blkio_schedule_list.next;
+             blkif = list_entry(ent, blkif_t, blkdev_list);
+             blkif_get(blkif);
+             remove_from_blkdev_list(blkif);
+             if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
+                 add_to_blkdev_list_tail(blkif);
+             blkif_put(blkif);
+         }
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+         /* Push the batch through to disc. */
+         run_task_queue(&tq_disk);
+ #endif
+     }
+ }
+ static void maybe_trigger_blkio_schedule(void)
+ {
+     /*
+      * Needed so that two processes, who together make the following predicate
+      * true, don't both read stale values and evaluate the predicate
+      * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
+      */
+     smp_mb();
+     if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+          !list_empty(&blkio_schedule_list) )
+         wake_up(&blkio_schedule_wait);
+ }
+ /******************************************************************
+  * COMPLETION CALLBACK -- Called as bh->b_end_io()
+  */
+ static void __end_block_io_op(pending_req_t *pending_req, int uptodate)
+ {
+     unsigned long flags;
+     /* An error fails the entire request. */
+     if ( !uptodate )
+     {
+         DPRINTK("Buffer not up-to-date at end of operation\n");
+         pending_req->status = BLKIF_RSP_ERROR;
+     }
+     if ( atomic_dec_and_test(&pending_req->pendcnt) )
+     {
+         int pending_idx = pending_req - pending_reqs;
+         fast_flush_area(pending_idx, pending_req->nr_pages);
+         make_response(pending_req->blkif, pending_req->id,
+                       pending_req->operation, pending_req->status);
+         blkif_put(pending_req->blkif);
+         spin_lock_irqsave(&pend_prod_lock, flags);
+         pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+         spin_unlock_irqrestore(&pend_prod_lock, flags);
+         maybe_trigger_blkio_schedule();
+     }
+ }
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ static void end_block_io_op(struct buffer_head *bh, int uptodate)
+ {
+     __end_block_io_op(bh->b_private, uptodate);
+     kmem_cache_free(buffer_head_cachep, bh);
+ }
+ #else
+ static int end_block_io_op(struct bio *bio, unsigned int done, int error)
+ {
+     if ( done || error )
+         __end_block_io_op(bio->bi_private, (done && !error));
+     bio_put(bio);
+     return error;
+ }
+ #endif
+ /******************************************************************************
+  * NOTIFICATION FROM GUEST OS.
+  */
+ irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+ {
+     blkif_t *blkif = dev_id;
+     add_to_blkdev_list_tail(blkif);
+     maybe_trigger_blkio_schedule();
+     return IRQ_HANDLED;
+ }
+ /******************************************************************
+  * DOWNWARD CALLS -- These interface with the block-device layer proper.
+  */
+ static int do_block_io_op(blkif_t *blkif, int max_to_do)
+ {
+     blkif_ring_t *blk_ring = blkif->blk_ring_base;
+     blkif_request_t *req;
+     BLKIF_RING_IDX i, rp;
+     int more_to_do = 0;
+     rp = blk_ring->req_prod;
+     rmb(); /* Ensure we see queued requests up to 'rp'. */
+     /* Take items off the comms ring, taking care not to overflow. */
+     for ( i = blkif->blk_req_cons; 
+           (i != rp) && ((i-blkif->blk_resp_prod) != BLKIF_RING_SIZE);
+           i++ )
+     {
+         if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
+         {
+             more_to_do = 1;
+             break;
+         }
+         
+         req = &blk_ring->ring[MASK_BLKIF_IDX(i)].req;
+         switch ( req->operation )
+         {
+         case BLKIF_OP_READ:
+         case BLKIF_OP_WRITE:
+             dispatch_rw_block_io(blkif, req);
+             break;
+         case BLKIF_OP_PROBE:
+             dispatch_probe(blkif, req);
+             break;
+         default:
+             DPRINTK("error: unknown block io operation [%d]\n",
+                     blk_ring->ring[i].req.operation);
+             make_response(blkif, blk_ring->ring[i].req.id, 
+                           blk_ring->ring[i].req.operation, BLKIF_RSP_ERROR);
+             break;
+         }
+     }
+     blkif->blk_req_cons = i;
+     return more_to_do;
+ }
+ static void dispatch_probe(blkif_t *blkif, blkif_request_t *req)
+ {
+     int rsp = BLKIF_RSP_ERROR;
+     int pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+     /* We expect one buffer only. */
+     if ( unlikely(req->nr_segments != 1) )
+         goto out;
+     /* Make sure the buffer is page-sized. */
+     if ( (blkif_first_sect(req->frame_and_sects[0]) != 0) ||
+          (blkif_last_sect(req->frame_and_sects[0]) != 7) )
+         goto out;
++#ifdef CONFIG_XEN_BLKDEV_TAP_BE
++    /* Grab the real frontend out of the probe message. */
++    alt_dom = (domid_t)req->frame_and_sects[1];
++#endif
++    
+     if ( HYPERVISOR_update_va_mapping_otherdomain(
+         MMAP_VADDR(pending_idx, 0) >> PAGE_SHIFT,
+         (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL },
 -
++        0, blkif->domid) ) {
++#ifdef CONFIG_XEN_BLKDEV_TAP_BE
++        /* That didn't work.  Try alt_dom. */
++        if ( HYPERVISOR_update_va_mapping_otherdomain(
++            MMAP_VADDR(pending_idx, 0) >> PAGE_SHIFT,
++            (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL },
++            0, alt_dom) )
++            goto out;
++#else  
+         goto out;
 -
++#endif
++    }
++    
+     rsp = vbd_probe(blkif, (vdisk_t *)MMAP_VADDR(pending_idx, 0), 
+                     PAGE_SIZE / sizeof(vdisk_t));
+  out:
+     fast_flush_area(pending_idx, 1);
+     make_response(blkif, req->id, req->operation, rsp);
+ }
+ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
+ {
+     extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); 
+     int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
+     short nr_sects;
+     unsigned long buffer, fas;
+     int i, tot_sects, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+     pending_req_t *pending_req;
+     unsigned long  remap_prot;
+     multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
+     /* We map virtual scatter/gather segments to physical segments. */
+     int new_segs, nr_psegs = 0;
+     phys_seg_t phys_seg[BLKIF_MAX_SEGMENTS_PER_REQUEST + 1];
+     /* Check that number of segments is sane. */
+     if ( unlikely(req->nr_segments == 0) || 
+          unlikely(req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST) )
+     {
+         DPRINTK("Bad number of segments in request (%d)\n", req->nr_segments);
+         goto bad_descriptor;
+     }
+     /*
+      * Check each address/size pair is sane, and convert into a
+      * physical device and block offset. Note that if the offset and size
+      * crosses a virtual extent boundary, we may end up with more
+      * physical scatter/gather segments than virtual segments.
+      */
+     for ( i = tot_sects = 0; i < req->nr_segments; i++, tot_sects += nr_sects )
+     {
+         fas      = req->frame_and_sects[i];
+         buffer   = (fas & PAGE_MASK) | (blkif_first_sect(fas) << 9);
+         nr_sects = blkif_last_sect(fas) - blkif_first_sect(fas) + 1;
+         if ( nr_sects <= 0 )
+             goto bad_descriptor;
+         phys_seg[nr_psegs].dev           = req->device;
+         phys_seg[nr_psegs].sector_number = req->sector_number + tot_sects;
+         phys_seg[nr_psegs].buffer        = buffer;
+         phys_seg[nr_psegs].nr_sects      = nr_sects;
+         /* Translate the request into the relevant 'physical device' */
+         new_segs = vbd_translate(&phys_seg[nr_psegs], blkif, operation);
+         if ( new_segs < 0 )
+         { 
+             DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n", 
+                     operation == READ ? "read" : "write", 
+                     req->sector_number + tot_sects, 
+                     req->sector_number + tot_sects + nr_sects, 
+                     req->device); 
+             goto bad_descriptor;
+         }
+   
+         nr_psegs += new_segs;
+         ASSERT(nr_psegs <= (BLKIF_MAX_SEGMENTS_PER_REQUEST+1));
+     }
+     /* Nonsensical zero-sized request? */
+     if ( unlikely(nr_psegs == 0) )
+         goto bad_descriptor;
+     if ( operation == READ )
+         remap_prot = _PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW;
+     else
+         remap_prot = _PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED;
+     for ( i = 0; i < nr_psegs; i++ )
+     {
+         mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain;
+         mcl[i].args[0] = MMAP_VADDR(pending_idx, i) >> PAGE_SHIFT;
+         mcl[i].args[1] = (phys_seg[i].buffer & PAGE_MASK) | remap_prot;
+         mcl[i].args[2] = 0;
++#ifdef CONFIG_XEN_BLKDEV_TAP_BE
++        mcl[i].args[3] = (alt_dom != 0) ? alt_dom : blkif->domid;
++#else
+         mcl[i].args[3] = blkif->domid;
 -
++#endif
+         phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
+             FOREIGN_FRAME(phys_seg[i].buffer >> PAGE_SHIFT);
+     }
+     if ( unlikely(HYPERVISOR_multicall(mcl, nr_psegs) != 0) )
+         BUG();
+     for ( i = 0; i < nr_psegs; i++ )
+     {
+         if ( unlikely(mcl[i].args[5] != 0) )
+         {
+             DPRINTK("invalid buffer -- could not remap it\n");
+             fast_flush_area(pending_idx, nr_psegs);
+             goto bad_descriptor;
+         }
+     }
+     pending_req = &pending_reqs[pending_idx];
+     pending_req->blkif     = blkif;
+     pending_req->id        = req->id;
+     pending_req->operation = operation;
+     pending_req->status    = BLKIF_RSP_OKAY;
+     pending_req->nr_pages  = nr_psegs;
+     atomic_set(&pending_req->pendcnt, nr_psegs);
+     pending_cons++;
+     blkif_get(blkif);
+     /* Now we pass each segment down to the real blkdev layer. */
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+     for ( i = 0; i < nr_psegs; i++ )
+     {
+         struct buffer_head *bh;
+         bh = kmem_cache_alloc(buffer_head_cachep, GFP_ATOMIC);
+         if ( unlikely(bh == NULL) )
+         {
+             __end_block_io_op(pending_req, 0);
+             continue;
+         }
+         memset(bh, 0, sizeof (struct buffer_head));
+         init_waitqueue_head(&bh->b_wait);
+         bh->b_size          = phys_seg[i].nr_sects << 9;
+         bh->b_dev           = phys_seg[i].dev;
+         bh->b_rdev          = phys_seg[i].dev;
+         bh->b_rsector       = (unsigned long)phys_seg[i].sector_number;
+         bh->b_data          = (char *)MMAP_VADDR(pending_idx, i) +
+             (phys_seg[i].buffer & ~PAGE_MASK);
+         bh->b_page          = virt_to_page(MMAP_VADDR(pending_idx, i));
+         bh->b_end_io        = end_block_io_op;
+         bh->b_private       = pending_req;
+         bh->b_state = (1 << BH_Mapped) | (1 << BH_Lock) | 
+             (1 << BH_Req) | (1 << BH_Launder);
+         if ( operation == WRITE )
+             bh->b_state |= (1 << BH_JBD) | (1 << BH_Req) | (1 << BH_Uptodate);
+         atomic_set(&bh->b_count, 1);
+         /* Dispatch a single request. We'll flush it to disc later. */
+         generic_make_request(operation, bh);
+     }
+ #else
+     for ( i = 0; i < nr_psegs; i++ )
+     {
+         struct bio *bio;
+         struct bio_vec *bv;
+         bio = bio_alloc(GFP_ATOMIC, 1);
+         if ( unlikely(bio == NULL) )
+         {
+             __end_block_io_op(pending_req, 0);
+             continue;
+         }
+         bio->bi_bdev    = phys_seg[i].bdev;
+         bio->bi_private = pending_req;
+         bio->bi_end_io  = end_block_io_op;
+         bio->bi_sector  = phys_seg[i].sector_number;
+         bio->bi_rw      = operation;
+         bv = bio_iovec_idx(bio, 0);
+         bv->bv_page   = virt_to_page(MMAP_VADDR(pending_idx, i));
+         bv->bv_len    = phys_seg[i].nr_sects << 9;
+         bv->bv_offset = phys_seg[i].buffer & ~PAGE_MASK;
+         bio->bi_size    = bv->bv_len;
+         bio->bi_vcnt++;
+         submit_bio(operation, bio);
+     }
+ #endif
+     return;
+  bad_descriptor:
+     make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+ } 
+ /******************************************************************
+  * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
+  */
+ static void make_response(blkif_t *blkif, unsigned long id, 
+                           unsigned short op, int st)
+ {
+     blkif_response_t *resp;
+     unsigned long     flags;
+     /* Place on the response ring for the relevant domain. */ 
+     spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+     resp = &blkif->blk_ring_base->
+         ring[MASK_BLKIF_IDX(blkif->blk_resp_prod)].resp;
+     resp->id        = id;
+     resp->operation = op;
+     resp->status    = st;
+     wmb(); /* Ensure other side can see the response fields. */
+     blkif->blk_ring_base->resp_prod = ++blkif->blk_resp_prod;
+     spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+     /* Kick the relevant domain. */
+     notify_via_evtchn(blkif->evtchn);
+ }
+ void blkif_deschedule(blkif_t *blkif)
+ {
+     remove_from_blkdev_list(blkif);
+ }
+ static int __init blkif_init(void)
+ {
+     int i;
+     if ( !(xen_start_info.flags & SIF_INITDOMAIN) &&
+          !(xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
+         return 0;
+     blkif_interface_init();
+     if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 )
+         BUG();
+     pending_cons = 0;
+     pending_prod = MAX_PENDING_REQS;
+     memset(pending_reqs, 0, sizeof(pending_reqs));
+     for ( i = 0; i < MAX_PENDING_REQS; i++ )
+         pending_ring[i] = i;
+     
+     spin_lock_init(&blkio_schedule_list_lock);
+     INIT_LIST_HEAD(&blkio_schedule_list);
+     if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
+         BUG();
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+     buffer_head_cachep = kmem_cache_create(
+         "buffer_head_cache", sizeof(struct buffer_head),
+         0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ #endif
+     blkif_ctrlif_init();
++    
++#ifdef CONFIG_XEN_BLKDEV_TAP_BE
++    printk(KERN_ALERT "NOTE: Blkif backend is running with tap support on!\n");
++#endif
+     return 0;
+ }
+ __initcall(blkif_init);
index 0000000000000000000000000000000000000000,957db7243250e1d9257d60492ea6703221c7c6d5..1d65f29b45d98d25594fffda5c5eb8f2de4c512e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1416 +1,1418 @@@
 -        WPRINTK(" Invalid blkif: handle=%u", status->handle);
+ /******************************************************************************
+  * blkfront.c
+  * 
+  * XenLinux virtual block-device driver.
+  * 
+  * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+  * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+  * Copyright (c) 2004, Christian Limpach
+  * 
+  * This file may be distributed separately from the Linux kernel, or
+  * incorporated into other software packages, subject to the following license:
+  * 
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+  * of this source file (the "Software"), to deal in the Software without
+  * restriction, including without limitation the rights to use, copy, modify,
+  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  * and to permit persons to whom the Software is furnished to do so, subject to
+  * the following conditions:
+  * 
+  * The above copyright notice and this permission notice shall be included in
+  * all copies or substantial portions of the Software.
+  * 
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  * IN THE SOFTWARE.
+  */
+ #include <linux/version.h>
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ #include "block.h"
+ #else
+ #include "common.h"
+ #include <linux/blk.h>
+ #include <linux/tqueue.h>
+ #endif
+ #include <linux/cdrom.h>
+ #include <linux/sched.h>
+ #include <linux/interrupt.h>
+ #include <scsi/scsi.h>
+ #include <asm-xen/ctrl_if.h>
++#include <asm-xen/evtchn.h>
+ typedef unsigned char byte; /* from linux/ide.h */
+ /* Control whether runtime update of vbds is enabled. */
+ #define ENABLE_VBD_UPDATE 1
+ #if ENABLE_VBD_UPDATE
+ static void vbd_update(void);
+ #else
+ static void vbd_update(void){};
+ #endif
+ #define BLKIF_STATE_CLOSED       0
+ #define BLKIF_STATE_DISCONNECTED 1
+ #define BLKIF_STATE_CONNECTED    2
+ static char *blkif_state_name[] = {
+     [BLKIF_STATE_CLOSED]       = "closed",
+     [BLKIF_STATE_DISCONNECTED] = "disconnected",
+     [BLKIF_STATE_CONNECTED]    = "connected",
+ };
+ static char * blkif_status_name[] = {
+     [BLKIF_INTERFACE_STATUS_CLOSED]       = "closed",
+     [BLKIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected",
+     [BLKIF_INTERFACE_STATUS_CONNECTED]    = "connected",
+     [BLKIF_INTERFACE_STATUS_CHANGED]      = "changed",
+ };
+ #define WPRINTK(fmt, args...) printk(KERN_WARNING "xen_blk: " fmt, ##args)
+ static int blkif_handle = 0;
+ static unsigned int blkif_state = BLKIF_STATE_CLOSED;
+ static unsigned int blkif_evtchn = 0;
+ static unsigned int blkif_irq = 0;
+ static int blkif_control_rsp_valid;
+ static blkif_response_t blkif_control_rsp;
+ static blkif_ring_t *blk_ring = NULL;
+ static BLKIF_RING_IDX resp_cons; /* Response consumer for comms ring. */
+ static BLKIF_RING_IDX req_prod;  /* Private request producer.         */
+ unsigned long rec_ring_free;
+ blkif_request_t rec_ring[BLKIF_RING_SIZE];
+ static int recovery = 0;           /* "Recovery in progress" flag.  Protected
+                                     * by the blkif_io_lock */
+ /* We plug the I/O ring if the driver is suspended or if the ring is full. */
+ #define BLKIF_RING_FULL (((req_prod - resp_cons) == BLKIF_RING_SIZE) || \
+                          (blkif_state != BLKIF_STATE_CONNECTED))
+ static void kick_pending_request_queues(void);
+ int __init xlblk_init(void);
+ void blkif_completion( blkif_request_t *req );
+ static inline int GET_ID_FROM_FREELIST( void )
+ {
+     unsigned long free = rec_ring_free;
+     if ( free > BLKIF_RING_SIZE )
+         BUG();
+     rec_ring_free = rec_ring[free].id;
+     rec_ring[free].id = 0x0fffffee; /* debug */
+     return free;
+ }
+ static inline void ADD_ID_TO_FREELIST( unsigned long id )
+ {
+     rec_ring[id].id = rec_ring_free;
+     rec_ring_free = id;
+ }
+ /************************  COMMON CODE  (inlined)  ************************/
+ /* Kernel-specific definitions used in the common code */
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ #define DISABLE_SCATTERGATHER() 
+ #else
+ static int sg_operation = -1;
+ #define DISABLE_SCATTERGATHER() (sg_operation = -1)
+ #endif
+ static inline void translate_req_to_pfn(blkif_request_t *xreq,
+                                         blkif_request_t *req)
+ {
+     int i;
+     xreq->operation     = req->operation;
+     xreq->nr_segments   = req->nr_segments;
+     xreq->device        = req->device;
+     /* preserve id */
+     xreq->sector_number = req->sector_number;
+     for ( i = 0; i < req->nr_segments; i++ )
+         xreq->frame_and_sects[i] = machine_to_phys(req->frame_and_sects[i]);
+ }
+ static inline void translate_req_to_mfn(blkif_request_t *xreq,
+                                         blkif_request_t *req)
+ {
+     int i;
+     xreq->operation     = req->operation;
+     xreq->nr_segments   = req->nr_segments;
+     xreq->device        = req->device;
+     xreq->id            = req->id;   /* copy id (unlike above) */
+     xreq->sector_number = req->sector_number;
+     for ( i = 0; i < req->nr_segments; i++ )
+         xreq->frame_and_sects[i] = phys_to_machine(req->frame_and_sects[i]);
+ }
+ static inline void flush_requests(void)
+ {
+     DISABLE_SCATTERGATHER();
+     wmb(); /* Ensure that the frontend can see the requests. */
+     blk_ring->req_prod = req_prod;
+     notify_via_evtchn(blkif_evtchn);
+ }
+ /**************************  KERNEL VERSION 2.6  **************************/
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ __initcall(xlblk_init);
+ #if ENABLE_VBD_UPDATE
+ static void vbd_update(void)
+ {
+ }
+ #endif /* ENABLE_VBD_UPDATE */
+ static void kick_pending_request_queues(void)
+ {
+     if ( (xlbd_blk_queue != NULL) &&
+          test_bit(QUEUE_FLAG_STOPPED, &xlbd_blk_queue->queue_flags) )
+     {
+         blk_start_queue(xlbd_blk_queue);
+         /* XXXcl call to request_fn should not be needed but
+          * we get stuck without...  needs investigating
+          */
+         xlbd_blk_queue->request_fn(xlbd_blk_queue);
+     }
+ }
+ int blkif_open(struct inode *inode, struct file *filep)
+ {
+     struct gendisk *gd = inode->i_bdev->bd_disk;
+     struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data;
+     /* Update of usage count is protected by per-device semaphore. */
+     di->mi->usage++;
+     
+     return 0;
+ }
+ int blkif_release(struct inode *inode, struct file *filep)
+ {
+     struct gendisk *gd = inode->i_bdev->bd_disk;
+     struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data;
+     /*
+      * When usage drops to zero it may allow more VBD updates to occur.
+      * Update of usage count is protected by a per-device semaphore.
+      */
+     if (--di->mi->usage == 0) {
+         vbd_update();
+     }
+     return 0;
+ }
+ int blkif_ioctl(struct inode *inode, struct file *filep,
+                 unsigned command, unsigned long argument)
+ {
+     /*  struct gendisk *gd = inode->i_bdev->bd_disk; */
+     DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
+                   command, (long)argument, inode->i_rdev); 
+   
+     switch (command) {
+     case HDIO_GETGEO:
+         /* return ENOSYS to use defaults */
+         return -ENOSYS;
+     default:
+         printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
+                command);
+         return -ENOSYS;
+     }
+     return 0;
+ }
+ #if 0
+ /* check media change: should probably do something here in some cases :-) */
+ int blkif_check(kdev_t dev)
+ {
+     DPRINTK("blkif_check\n");
+     return 0;
+ }
+ int blkif_revalidate(kdev_t dev)
+ {
+     struct block_device *bd;
+     struct gendisk *gd;
+     xen_block_t *disk;
+     unsigned long capacity;
+     int i, rc = 0;
+     
+     if ( (bd = bdget(dev)) == NULL )
+         return -EINVAL;
+     /*
+      * Update of partition info, and check of usage count, is protected
+      * by the per-block-device semaphore.
+      */
+     down(&bd->bd_sem);
+     if ( ((gd = get_gendisk(dev)) == NULL) ||
+          ((disk = xldev_to_xldisk(dev)) == NULL) ||
+          ((capacity = gd->part[MINOR(dev)].nr_sects) == 0) )
+     {
+         rc = -EINVAL;
+         goto out;
+     }
+     if ( disk->usage > 1 )
+     {
+         rc = -EBUSY;
+         goto out;
+     }
+     /* Only reread partition table if VBDs aren't mapped to partitions. */
+     if ( !(gd->flags[MINOR(dev) >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) )
+     {
+         for ( i = gd->max_p - 1; i >= 0; i-- )
+         {
+             invalidate_device(dev+i, 1);
+             gd->part[MINOR(dev+i)].start_sect = 0;
+             gd->part[MINOR(dev+i)].nr_sects   = 0;
+             gd->sizes[MINOR(dev+i)]           = 0;
+         }
+         grok_partitions(gd, MINOR(dev)>>gd->minor_shift, gd->max_p, capacity);
+     }
+  out:
+     up(&bd->bd_sem);
+     bdput(bd);
+     return rc;
+ }
+ #endif
+ /*
+  * blkif_queue_request
+  *
+  * request block io 
+  * 
+  * id: for guest use only.
+  * operation: BLKIF_OP_{READ,WRITE,PROBE}
+  * buffer: buffer to read/write into. this should be a
+  *   virtual address in the guest os.
+  */
+ static int blkif_queue_request(struct request *req)
+ {
+     struct xlbd_disk_info *di =
+         (struct xlbd_disk_info *)req->rq_disk->private_data;
+     unsigned long buffer_ma;
+     blkif_request_t *ring_req;
+     struct bio *bio;
+     struct bio_vec *bvec;
+     int idx, s;
+     unsigned long id;
+     unsigned int fsect, lsect;
+     if (unlikely(blkif_state != BLKIF_STATE_CONNECTED))
+         return 1;
+     /* Fill out a communications ring structure. */
+     ring_req = &blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req;
+     id = GET_ID_FROM_FREELIST();
+     rec_ring[id].id = (unsigned long) req;
+     ring_req->id = id;
+     ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE :
+         BLKIF_OP_READ;
+     ring_req->sector_number = (blkif_sector_t)req->sector;
+     ring_req->device = di->xd_device;
+     s = 0;
+     ring_req->nr_segments = 0;
+     rq_for_each_bio(bio, req) {
+         bio_for_each_segment(bvec, bio, idx) {
+             buffer_ma = page_to_phys(bvec->bv_page);
+             if (unlikely((buffer_ma & ((1<<9)-1)) != 0))
+                 BUG();
+             fsect = bvec->bv_offset >> 9;
+             lsect = fsect + (bvec->bv_len >> 9) - 1;
+             if (unlikely(lsect > 7))
+                 BUG();
+             ring_req->frame_and_sects[ring_req->nr_segments++] =
+                 buffer_ma | (fsect << 3) | lsect;
+             s += bvec->bv_len >> 9;
+         }
+     }
+     req_prod++;
+     /* Keep a private copy so we can reissue requests when recovering. */
+     translate_req_to_pfn( &rec_ring[id], ring_req);
+     return 0;
+ }
+ /*
+  * do_blkif_request
+  *  read a block; request is in a request queue
+  */
+ void do_blkif_request(request_queue_t *rq)
+ {
+     struct request *req;
+     int queued;
+     DPRINTK("Entered do_blkif_request\n"); 
+     queued = 0;
+     while ((req = elv_next_request(rq)) != NULL) {
+         if (!blk_fs_request(req)) {
+             end_request(req, 0);
+             continue;
+         }
+         if ( BLKIF_RING_FULL )
+         {
+             blk_stop_queue(rq);
+             break;
+         }
+         DPRINTK("do_blk_req %p: cmd %p, sec %lx, (%u/%li) buffer:%p [%s]\n",
+                 req, req->cmd, req->sector, req->current_nr_sectors,
+                 req->nr_sectors, req->buffer,
+                 rq_data_dir(req) ? "write" : "read");
+         blkdev_dequeue_request(req);
+         if (blkif_queue_request(req)) {
+             blk_stop_queue(rq);
+             break;
+         }
+         queued++;
+     }
+     if (queued != 0)
+         flush_requests();
+ }
+ static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
+ {
+     struct request *req;
+     blkif_response_t *bret;
+     BLKIF_RING_IDX i, rp;
+     unsigned long flags; 
+     spin_lock_irqsave(&blkif_io_lock, flags);     
+     if ( unlikely(blkif_state == BLKIF_STATE_CLOSED) || 
+          unlikely(recovery) )
+     {
+         spin_unlock_irqrestore(&blkif_io_lock, flags);
+         return IRQ_HANDLED;
+     }
+     rp = blk_ring->resp_prod;
+     rmb(); /* Ensure we see queued responses up to 'rp'. */
+     for ( i = resp_cons; i != rp; i++ )
+     {
+       unsigned long id;
+         bret = &blk_ring->ring[MASK_BLKIF_IDX(i)].resp;
+       id = bret->id;
+       req = (struct request *)rec_ring[id].id;
+       blkif_completion( &rec_ring[id] );
+       ADD_ID_TO_FREELIST(id); /* overwrites req */
+         switch ( bret->operation )
+         {
+         case BLKIF_OP_READ:
+         case BLKIF_OP_WRITE:
+             if ( unlikely(bret->status != BLKIF_RSP_OKAY) )
+                 DPRINTK("Bad return from blkdev data request: %x\n",
+                         bret->status);
+           
+             if ( unlikely(end_that_request_first
+                           (req, 
+                            (bret->status == BLKIF_RSP_OKAY),
+                            req->hard_nr_sectors)) )
+                 BUG();
+             end_that_request_last(req);
+             break;
+         case BLKIF_OP_PROBE:
+             memcpy(&blkif_control_rsp, bret, sizeof(*bret));
+             blkif_control_rsp_valid = 1;
+             break;
+         default:
+             BUG();
+         }
+     }
+     
+     resp_cons = i;
+     kick_pending_request_queues();
+     spin_unlock_irqrestore(&blkif_io_lock, flags);
+     return IRQ_HANDLED;
+ }
+ #else
+ /**************************  KERNEL VERSION 2.4  **************************/
+ static kdev_t        sg_dev;
+ static unsigned long sg_next_sect;
+ /*
+  * Request queues with outstanding work, but ring is currently full.
+  * We need no special lock here, as we always access this with the
+  * blkif_io_lock held. We only need a small maximum list.
+  */
+ #define MAX_PENDING 8
+ static request_queue_t *pending_queues[MAX_PENDING];
+ static int nr_pending;
+ #define blkif_io_lock io_request_lock
+ /*============================================================================*/
+ #if ENABLE_VBD_UPDATE
+ /*
+  * blkif_update_int/update-vbds_task - handle VBD update events.
+  *  Schedule a task for keventd to run, which will update the VBDs and perform 
+  *  the corresponding updates to our view of VBD state.
+  */
+ static void update_vbds_task(void *unused)
+ { 
+     xlvbd_update_vbds();
+ }
+ static void vbd_update(void)
+ {
+     static struct tq_struct update_tq;
+     update_tq.routine = update_vbds_task;
+     schedule_task(&update_tq);
+ }
+ #endif /* ENABLE_VBD_UPDATE */
+ /*============================================================================*/
+ static void kick_pending_request_queues(void)
+ {
+     /* We kick pending request queues if the ring is reasonably empty. */
+     if ( (nr_pending != 0) && 
+          ((req_prod - resp_cons) < (BLKIF_RING_SIZE >> 1)) )
+     {
+         /* Attempt to drain the queue, but bail if the ring becomes full. */
+         while ( (nr_pending != 0) && !BLKIF_RING_FULL )
+             do_blkif_request(pending_queues[--nr_pending]);
+     }
+ }
+ int blkif_open(struct inode *inode, struct file *filep)
+ {
+     short xldev = inode->i_rdev; 
+     struct gendisk *gd = get_gendisk(xldev);
+     xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
+     short minor = MINOR(xldev); 
+     if ( gd->part[minor].nr_sects == 0 )
+     { 
+         /*
+          * Device either doesn't exist, or has zero capacity; we use a few
+          * cheesy heuristics to return the relevant error code
+          */
+         if ( (gd->sizes[minor >> gd->minor_shift] != 0) ||
+              ((minor & (gd->max_p - 1)) != 0) )
+         { 
+             /*
+              * We have a real device, but no such partition, or we just have a
+              * partition number so guess this is the problem.
+              */
+             return -ENXIO;     /* no such device or address */
+         }
+         else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE )
+         {
+             /* This is a removable device => assume that media is missing. */ 
+             return -ENOMEDIUM; /* media not present (this is a guess) */
+         } 
+         else
+         { 
+             /* Just go for the general 'no such device' error. */
+             return -ENODEV;    /* no such device */
+         }
+     }
+     
+     /* Update of usage count is protected by per-device semaphore. */
+     disk->usage++;
+     return 0;
+ }
+ int blkif_release(struct inode *inode, struct file *filep)
+ {
+     xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
+     /*
+      * When usage drops to zero it may allow more VBD updates to occur.
+      * Update of usage count is protected by a per-device semaphore.
+      */
+     if ( --disk->usage == 0 ) {
+         vbd_update();
+     }
+     return 0;
+ }
+ int blkif_ioctl(struct inode *inode, struct file *filep,
+                 unsigned command, unsigned long argument)
+ {
+     kdev_t dev = inode->i_rdev;
+     struct hd_geometry *geo = (struct hd_geometry *)argument;
+     struct gendisk *gd;     
+     struct hd_struct *part; 
+     int i;
+     unsigned short cylinders;
+     byte heads, sectors;
+     /* NB. No need to check permissions. That is done for us. */
+     
+     DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
+                   command, (long) argument, dev); 
+   
+     gd = get_gendisk(dev);
+     part = &gd->part[MINOR(dev)]; 
+     switch ( command )
+     {
+     case BLKGETSIZE:
+         DPRINTK_IOCTL("   BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects); 
+         return put_user(part->nr_sects, (unsigned long *) argument);
+     case BLKGETSIZE64:
+         DPRINTK_IOCTL("   BLKGETSIZE64: %x %llx\n", BLKGETSIZE64,
+                       (u64)part->nr_sects * 512);
+         return put_user((u64)part->nr_sects * 512, (u64 *) argument);
+     case BLKRRPART:                               /* re-read partition table */
+         DPRINTK_IOCTL("   BLKRRPART: %x\n", BLKRRPART);
+         return blkif_revalidate(dev);
+     case BLKSSZGET:
+         return hardsect_size[MAJOR(dev)][MINOR(dev)]; 
+     case BLKBSZGET:                                        /* get block size */
+         DPRINTK_IOCTL("   BLKBSZGET: %x\n", BLKBSZGET);
+         break;
+     case BLKBSZSET:                                        /* set block size */
+         DPRINTK_IOCTL("   BLKBSZSET: %x\n", BLKBSZSET);
+         break;
+     case BLKRASET:                                         /* set read-ahead */
+         DPRINTK_IOCTL("   BLKRASET: %x\n", BLKRASET);
+         break;
+     case BLKRAGET:                                         /* get read-ahead */
+         DPRINTK_IOCTL("   BLKRAFET: %x\n", BLKRAGET);
+         break;
+     case HDIO_GETGEO:
+         DPRINTK_IOCTL("   HDIO_GETGEO: %x\n", HDIO_GETGEO);
+         if (!argument) return -EINVAL;
+         /* We don't have real geometry info, but let's at least return
+          values consistent with the size of the device */
+         heads = 0xff;
+         sectors = 0x3f; 
+         cylinders = part->nr_sects / (heads * sectors);
+         if (put_user(0x00,  (unsigned long *) &geo->start)) return -EFAULT;
+         if (put_user(heads,  (byte *)&geo->heads)) return -EFAULT;
+         if (put_user(sectors,  (byte *)&geo->sectors)) return -EFAULT;
+         if (put_user(cylinders, (unsigned short *)&geo->cylinders)) return -EFAULT;
+         return 0;
+     case HDIO_GETGEO_BIG: 
+         DPRINTK_IOCTL("   HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG);
+         if (!argument) return -EINVAL;
+         /* We don't have real geometry info, but let's at least return
+          values consistent with the size of the device */
+         heads = 0xff;
+         sectors = 0x3f; 
+         cylinders = part->nr_sects / (heads * sectors);
+         if (put_user(0x00,  (unsigned long *) &geo->start))  return -EFAULT;
+         if (put_user(heads,  (byte *)&geo->heads))   return -EFAULT;
+         if (put_user(sectors,  (byte *)&geo->sectors)) return -EFAULT;
+         if (put_user(cylinders, (unsigned int *) &geo->cylinders)) return -EFAULT;
+         return 0;
+     case CDROMMULTISESSION:
+         DPRINTK("FIXME: support multisession CDs later\n");
+         for ( i = 0; i < sizeof(struct cdrom_multisession); i++ )
+             if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT;
+         return 0;
+     case SCSI_IOCTL_GET_BUS_NUMBER:
+         DPRINTK("FIXME: SCSI_IOCTL_GET_BUS_NUMBER ioctl in XL blkif");
+         return -ENOSYS;
+     default:
+         printk(KERN_ALERT "ioctl %08x not supported by XL blkif\n", command);
+         return -ENOSYS;
+     }
+     
+     return 0;
+ }
+ /* check media change: should probably do something here in some cases :-) */
+ int blkif_check(kdev_t dev)
+ {
+     DPRINTK("blkif_check\n");
+     return 0;
+ }
+ int blkif_revalidate(kdev_t dev)
+ {
+     struct block_device *bd;
+     struct gendisk *gd;
+     xl_disk_t *disk;
+     unsigned long capacity;
+     int i, rc = 0;
+     
+     if ( (bd = bdget(dev)) == NULL )
+         return -EINVAL;
+     /*
+      * Update of partition info, and check of usage count, is protected
+      * by the per-block-device semaphore.
+      */
+     down(&bd->bd_sem);
+     if ( ((gd = get_gendisk(dev)) == NULL) ||
+          ((disk = xldev_to_xldisk(dev)) == NULL) ||
+          ((capacity = gd->part[MINOR(dev)].nr_sects) == 0) )
+     {
+         rc = -EINVAL;
+         goto out;
+     }
+     if ( disk->usage > 1 )
+     {
+         rc = -EBUSY;
+         goto out;
+     }
+     /* Only reread partition table if VBDs aren't mapped to partitions. */
+     if ( !(gd->flags[MINOR(dev) >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) )
+     {
+         for ( i = gd->max_p - 1; i >= 0; i-- )
+         {
+             invalidate_device(dev+i, 1);
+             gd->part[MINOR(dev+i)].start_sect = 0;
+             gd->part[MINOR(dev+i)].nr_sects   = 0;
+             gd->sizes[MINOR(dev+i)]           = 0;
+         }
+         grok_partitions(gd, MINOR(dev)>>gd->minor_shift, gd->max_p, capacity);
+     }
+  out:
+     up(&bd->bd_sem);
+     bdput(bd);
+     return rc;
+ }
+ /*
+  * blkif_queue_request
+  *
+  * request block io 
+  * 
+  * id: for guest use only.
+  * operation: BLKIF_OP_{READ,WRITE,PROBE}
+  * buffer: buffer to read/write into. this should be a
+  *   virtual address in the guest os.
+  */
+ static int blkif_queue_request(unsigned long   id,
+                                int             operation,
+                                char *          buffer,
+                                unsigned long   sector_number,
+                                unsigned short  nr_sectors,
+                                kdev_t          device)
+ {
+     unsigned long       buffer_ma = virt_to_bus(buffer);
+     unsigned long       xid;
+     struct gendisk     *gd;
+     blkif_request_t    *req;
+     struct buffer_head *bh;
+     unsigned int        fsect, lsect;
+     fsect = (buffer_ma & ~PAGE_MASK) >> 9;
+     lsect = fsect + nr_sectors - 1;
+     /* Buffer must be sector-aligned. Extent mustn't cross a page boundary. */
+     if ( unlikely((buffer_ma & ((1<<9)-1)) != 0) )
+         BUG();
+     if ( lsect > 7 )
+         BUG();
+     buffer_ma &= PAGE_MASK;
+     if ( unlikely(blkif_state != BLKIF_STATE_CONNECTED) )
+         return 1;
+     switch ( operation )
+     {
+     case BLKIF_OP_READ:
+     case BLKIF_OP_WRITE:
+         gd = get_gendisk(device); 
+         /*
+          * Update the sector_number we'll pass down as appropriate; note that
+          * we could sanity check that resulting sector will be in this
+          * partition, but this will happen in driver backend anyhow.
+          */
+         sector_number += gd->part[MINOR(device)].start_sect;
+         /*
+          * If this unit doesn't consist of virtual partitions then we clear 
+          * the partn bits from the device number.
+          */
+         if ( !(gd->flags[MINOR(device)>>gd->minor_shift] & 
+                GENHD_FL_VIRT_PARTNS) )
+             device &= ~(gd->max_p - 1);
+         if ( (sg_operation == operation) &&
+              (sg_dev == device) &&
+              (sg_next_sect == sector_number) )
+         {
+             req = &blk_ring->ring[MASK_BLKIF_IDX(req_prod-1)].req;
+             bh = (struct buffer_head *)id;
+           
+             bh->b_reqnext = (struct buffer_head *)rec_ring[req->id].id;
+           
+           rec_ring[req->id].id = id;
+             req->frame_and_sects[req->nr_segments] = 
+                 buffer_ma | (fsect<<3) | lsect;
+             if ( ++req->nr_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST )
+                 sg_next_sect += nr_sectors;
+             else
+                 DISABLE_SCATTERGATHER();
+             /* Update the copy of the request in the recovery ring. */
+             translate_req_to_pfn(&rec_ring[req->id], req );
+             return 0;
+         }
+         else if ( BLKIF_RING_FULL )
+         {
+             return 1;
+         }
+         else
+         {
+             sg_operation = operation;
+             sg_dev       = device;
+             sg_next_sect = sector_number + nr_sectors;
+         }
+         break;
+     default:
+         panic("unknown op %d\n", operation);
+     }
+     /* Fill out a communications ring structure. */
+     req = &blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req;
+     xid = GET_ID_FROM_FREELIST();
+     rec_ring[xid].id = id;
+     req->id            = xid;
+     req->operation     = operation;
+     req->sector_number = (blkif_sector_t)sector_number;
+     req->device        = device; 
+     req->nr_segments   = 1;
+     req->frame_and_sects[0] = buffer_ma | (fsect<<3) | lsect;
+     req_prod++;
+     /* Keep a private copy so we can reissue requests when recovering. */    
+     translate_req_to_pfn(&rec_ring[xid], req );
+     return 0;
+ }
+ /*
+  * do_blkif_request
+  *  read a block; request is in a request queue
+  */
+ void do_blkif_request(request_queue_t *rq)
+ {
+     struct request *req;
+     struct buffer_head *bh, *next_bh;
+     int rw, nsect, full, queued = 0;
+     DPRINTK("Entered do_blkif_request\n"); 
+     while ( !rq->plugged && !list_empty(&rq->queue_head))
+     {
+         if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) 
+             goto out;
+   
+         DPRINTK("do_blkif_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
+                 req, req->cmd, req->sector,
+                 req->current_nr_sectors, req->nr_sectors, req->bh);
+         rw = req->cmd;
+         if ( rw == READA )
+             rw = READ;
+         if ( unlikely((rw != READ) && (rw != WRITE)) )
+             panic("XenoLinux Virtual Block Device: bad cmd: %d\n", rw);
+         req->errors = 0;
+         bh = req->bh;
+         while ( bh != NULL )
+         {
+             next_bh = bh->b_reqnext;
+             bh->b_reqnext = NULL;
+             full = blkif_queue_request(
+                 (unsigned long)bh,
+                 (rw == READ) ? BLKIF_OP_READ : BLKIF_OP_WRITE, 
+                 bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev);
+             if ( full )
+             { 
+                 bh->b_reqnext = next_bh;
+                 pending_queues[nr_pending++] = rq;
+                 if ( unlikely(nr_pending >= MAX_PENDING) )
+                     BUG();
+                 goto out; 
+             }
+             queued++;
+             /* Dequeue the buffer head from the request. */
+             nsect = bh->b_size >> 9;
+             bh = req->bh = next_bh;
+             
+             if ( bh != NULL )
+             {
+                 /* There's another buffer head to do. Update the request. */
+                 req->hard_sector += nsect;
+                 req->hard_nr_sectors -= nsect;
+                 req->sector = req->hard_sector;
+                 req->nr_sectors = req->hard_nr_sectors;
+                 req->current_nr_sectors = bh->b_size >> 9;
+                 req->buffer = bh->b_data;
+             }
+             else
+             {
+                 /* That was the last buffer head. Finalise the request. */
+                 if ( unlikely(end_that_request_first(req, 1, "XenBlk")) )
+                     BUG();
+                 blkdev_dequeue_request(req);
+                 end_that_request_last(req);
+             }
+         }
+     }
+  out:
+     if ( queued != 0 )
+         flush_requests();
+ }
+ static void blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
+ {
+     BLKIF_RING_IDX i, rp; 
+     unsigned long flags; 
+     struct buffer_head *bh, *next_bh;
+     
+     spin_lock_irqsave(&io_request_lock, flags);     
+     if ( unlikely(blkif_state == BLKIF_STATE_CLOSED || recovery) )
+     {
+         spin_unlock_irqrestore(&io_request_lock, flags);
+         return;
+     }
+     rp = blk_ring->resp_prod;
+     rmb(); /* Ensure we see queued responses up to 'rp'. */
+     for ( i = resp_cons; i != rp; i++ )
+     {
+       unsigned long id;
+         blkif_response_t *bret = &blk_ring->ring[MASK_BLKIF_IDX(i)].resp;
+       id = bret->id;
+       bh = (struct buffer_head *)rec_ring[id].id; 
+       blkif_completion( &rec_ring[id] );
+       ADD_ID_TO_FREELIST(id);
+         switch ( bret->operation )
+         {
+         case BLKIF_OP_READ:
+         case BLKIF_OP_WRITE:
+             if ( unlikely(bret->status != BLKIF_RSP_OKAY) )
+                 DPRINTK("Bad return from blkdev data request: %lx\n",
+                         bret->status);
+             for ( ; bh != NULL; bh = next_bh )
+             {
+                 next_bh = bh->b_reqnext;
+                 bh->b_reqnext = NULL;
+                 bh->b_end_io(bh, bret->status == BLKIF_RSP_OKAY);
+             }
+             break;
+         case BLKIF_OP_PROBE:
+             memcpy(&blkif_control_rsp, bret, sizeof(*bret));
+             blkif_control_rsp_valid = 1;
+             break;
+         default:
+             BUG();
+         }
+     }
+     
+     resp_cons = i;
+     kick_pending_request_queues();
+     spin_unlock_irqrestore(&io_request_lock, flags);
+ }
+ #endif
+ /*****************************  COMMON CODE  *******************************/
+ void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp)
+ {
+     unsigned long flags, id;
+  retry:
+     while ( (req_prod - resp_cons) == BLKIF_RING_SIZE )
+     {
+         set_current_state(TASK_INTERRUPTIBLE);
+         schedule_timeout(1);
+     }
+     spin_lock_irqsave(&blkif_io_lock, flags);
+     if ( (req_prod - resp_cons) == BLKIF_RING_SIZE )
+     {
+         spin_unlock_irqrestore(&blkif_io_lock, flags);
+         goto retry;
+     }
+     DISABLE_SCATTERGATHER();
+     blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req = *req;    
+     id = GET_ID_FROM_FREELIST();
+     blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req.id = id;
+     rec_ring[id].id = (unsigned long) req;
+     translate_req_to_pfn( &rec_ring[id], req );
+     req_prod++;
+     flush_requests();
+     spin_unlock_irqrestore(&blkif_io_lock, flags);
+     while ( !blkif_control_rsp_valid )
+     {
+         set_current_state(TASK_INTERRUPTIBLE);
+         schedule_timeout(1);
+     }
+     memcpy(rsp, &blkif_control_rsp, sizeof(*rsp));
+     blkif_control_rsp_valid = 0;
+ }
+ /* Send a driver status notification to the domain controller. */
+ static void send_driver_status(int ok)
+ {
+     ctrl_msg_t cmsg = {
+         .type    = CMSG_BLKIF_FE,
+         .subtype = CMSG_BLKIF_FE_DRIVER_STATUS,
+         .length  = sizeof(blkif_fe_driver_status_t),
+     };
+     blkif_fe_driver_status_t *msg = (void*)cmsg.msg;
+     
+     msg->status = (ok ? BLKIF_DRIVER_STATUS_UP : BLKIF_DRIVER_STATUS_DOWN);
+     ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+ }
+ /* Tell the controller to bring up the interface. */
+ static void blkif_send_interface_connect(void)
+ {
+     ctrl_msg_t cmsg = {
+         .type    = CMSG_BLKIF_FE,
+         .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT,
+         .length  = sizeof(blkif_fe_interface_connect_t),
+     };
+     blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
+     
+     msg->handle      = 0;
+     msg->shmem_frame = (virt_to_machine(blk_ring) >> PAGE_SHIFT);
+     
+     ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+ }
+ static void blkif_free(void)
+ {
+     /* Prevent new requests being issued until we fix things up. */
+     spin_lock_irq(&blkif_io_lock);
+     recovery = 1;
+     blkif_state = BLKIF_STATE_DISCONNECTED;
+     spin_unlock_irq(&blkif_io_lock);
+     /* Free resources associated with old device channel. */
+     if ( blk_ring != NULL )
+     {
+         free_page((unsigned long)blk_ring);
+         blk_ring = NULL;
+     }
+     free_irq(blkif_irq, NULL);
+     blkif_irq = 0;
+     
+     unbind_evtchn_from_irq(blkif_evtchn);
+     blkif_evtchn = 0;
+ }
+ static void blkif_close(void)
+ {
+ }
+ /* Move from CLOSED to DISCONNECTED state. */
+ static void blkif_disconnect(void)
+ {
+     if ( blk_ring != NULL )
+         free_page((unsigned long)blk_ring);
+     blk_ring = (blkif_ring_t *)__get_free_page(GFP_KERNEL);
+     blk_ring->req_prod = blk_ring->resp_prod = resp_cons = req_prod = 0;
+     blkif_state  = BLKIF_STATE_DISCONNECTED;
+     blkif_send_interface_connect();
+ }
+ static void blkif_reset(void)
+ {
+     blkif_free();
+     blkif_disconnect();
+ }
+ static void blkif_recover(void)
+ {
+     int i;
+     /* Hmm, requests might be re-ordered when we re-issue them.
+      * This will need to be fixed once we have barriers */
+     /* Stage 1 : Find active and move to safety. */
+     for ( i = 0; i < BLKIF_RING_SIZE; i++ )
+     {
+         if ( rec_ring[i].id >= PAGE_OFFSET )
+         {
+             translate_req_to_mfn(
+                 &blk_ring->ring[req_prod].req, &rec_ring[i]);
+             req_prod++;
+         }
+     }
+     /* Stage 2 : Set up shadow list. */
+     for ( i = 0; i < req_prod; i++ ) 
+     {
+         rec_ring[i].id = blk_ring->ring[i].req.id;            
+         blk_ring->ring[i].req.id = i;
+         translate_req_to_pfn(&rec_ring[i], &blk_ring->ring[i].req);
+     }
+     /* Stage 3 : Set up free list. */
+     for ( ; i < BLKIF_RING_SIZE; i++ )
+         rec_ring[i].id = i+1;
+     rec_ring_free = req_prod;
+     rec_ring[BLKIF_RING_SIZE-1].id = 0x0fffffff;
+     /* blk_ring->req_prod will be set when we flush_requests().*/
+     wmb();
+     /* Switch off recovery mode, using a memory barrier to ensure that
+      * it's seen before we flush requests - we don't want to miss any
+      * interrupts. */
+     recovery = 0;
+     wmb();
+     /* Kicks things back into life. */
+     flush_requests();
+     /* Now safe to left other peope use interface. */
+     blkif_state = BLKIF_STATE_CONNECTED;
+ }
+ static void blkif_connect(blkif_fe_interface_status_t *status)
+ {
+     int err = 0;
+     blkif_evtchn = status->evtchn;
+     blkif_irq    = bind_evtchn_to_irq(blkif_evtchn);
+     err = request_irq(blkif_irq, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL);
+     if ( err )
+     {
+         printk(KERN_ALERT "xen_blk: request_irq failed (err=%d)\n", err);
+         return;
+     }
+     if ( recovery ) 
+     {
+         blkif_recover();
+     } 
+     else 
+     {
+         /* Transition to connected in case we need to do 
+          *  a partition probe on a whole disk. */
+         blkif_state = BLKIF_STATE_CONNECTED;
+         
+         /* Probe for discs attached to the interface. */
+         xlvbd_init();
+     }
+     
+     /* Kick pending requests. */
+     spin_lock_irq(&blkif_io_lock);
+     kick_pending_request_queues();
+     spin_unlock_irq(&blkif_io_lock);
+ }
+ static void unexpected(blkif_fe_interface_status_t *status)
+ {
+     DPRINTK(" Unexpected blkif status %s in state %s\n", 
+             blkif_status_name[status->status],
+             blkif_state_name[blkif_state]);
+ }
+ static void blkif_status(blkif_fe_interface_status_t *status)
+ {
+     if ( status->handle != blkif_handle )
+     {
++        WPRINTK(" Invalid blkif: handle=%u\n", status->handle);
++        unexpected(status);
+         return;
+     }
+     switch ( status->status ) 
+     {
+     case BLKIF_INTERFACE_STATUS_CLOSED:
+         switch ( blkif_state )
+         {
+         case BLKIF_STATE_CLOSED:
+             unexpected(status);
+             break;
+         case BLKIF_STATE_DISCONNECTED:
+         case BLKIF_STATE_CONNECTED:
+             unexpected(status);
+             blkif_close();
+             break;
+         }
+         break;
+     case BLKIF_INTERFACE_STATUS_DISCONNECTED:
+         switch ( blkif_state )
+         {
+         case BLKIF_STATE_CLOSED:
+             blkif_disconnect();
+             break;
+         case BLKIF_STATE_DISCONNECTED:
+         case BLKIF_STATE_CONNECTED:
+             /* unexpected(status); */ /* occurs during suspend/resume */
+             blkif_reset();
+             break;
+         }
+         break;
+     case BLKIF_INTERFACE_STATUS_CONNECTED:
+         switch ( blkif_state )
+         {
+         case BLKIF_STATE_CLOSED:
+             unexpected(status);
+             blkif_disconnect();
+             blkif_connect(status);
+             break;
+         case BLKIF_STATE_DISCONNECTED:
+             blkif_connect(status);
+             break;
+         case BLKIF_STATE_CONNECTED:
+             unexpected(status);
+             blkif_connect(status);
+             break;
+         }
+         break;
+    case BLKIF_INTERFACE_STATUS_CHANGED:
+         switch ( blkif_state )
+         {
+         case BLKIF_STATE_CLOSED:
+         case BLKIF_STATE_DISCONNECTED:
+             unexpected(status);
+             break;
+         case BLKIF_STATE_CONNECTED:
+             vbd_update();
+             break;
+         }
+        break;
+     default:
+         WPRINTK(" Invalid blkif status: %d\n", status->status);
+         break;
+     }
+ }
+ static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
+ {
+     switch ( msg->subtype )
+     {
+     case CMSG_BLKIF_FE_INTERFACE_STATUS:
+         if ( msg->length != sizeof(blkif_fe_interface_status_t) )
+             goto parse_error;
+         blkif_status((blkif_fe_interface_status_t *)
+                      &msg->msg[0]);
+         break;        
+     default:
+         goto parse_error;
+     }
+     ctrl_if_send_response(msg);
+     return;
+  parse_error:
+     msg->length = 0;
+     ctrl_if_send_response(msg);
+ }
+ int wait_for_blkif(void)
+ {
+     int err = 0;
+     int i;
+     send_driver_status(1);
+     /*
+      * We should read 'nr_interfaces' from response message and wait
+      * for notifications before proceeding. For now we assume that we
+      * will be notified of exactly one interface.
+      */
+     for ( i=0; (blkif_state != BLKIF_STATE_CONNECTED) && (i < 10*HZ); i++ )
+     {
+         set_current_state(TASK_INTERRUPTIBLE);
+         schedule_timeout(1);
+     }
+     if ( blkif_state != BLKIF_STATE_CONNECTED )
+     {
+         printk(KERN_INFO "xen_blk: Timeout connecting to device!\n");
+         err = -ENOSYS;
+     }
+     return err;
+ }
+ int __init xlblk_init(void)
+ {
+     int i;
+     
+     if ( (xen_start_info.flags & SIF_INITDOMAIN) ||
+          (xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
+         return 0;
+     printk(KERN_INFO "xen_blk: Initialising virtual block device driver\n");
+     rec_ring_free = 0;
+     for ( i = 0; i < BLKIF_RING_SIZE; i++ )
+       rec_ring[i].id = i+1;
+     rec_ring[BLKIF_RING_SIZE-1].id = 0x0fffffff;
+     (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx,
+                                     CALLBACK_IN_BLOCKING_CONTEXT);
+     wait_for_blkif();
+     return 0;
+ }
+ void blkdev_suspend(void)
+ {
+ }
+ void blkdev_resume(void)
+ {
+     send_driver_status(1);
+ }
+ /* XXXXX THIS IS A TEMPORARY FUNCTION UNTIL WE GET GRANT TABLES */
+ void blkif_completion(blkif_request_t *req)
+ {
+     int i;
+     switch ( req->operation )
+     {
+     case BLKIF_OP_READ:
+       for ( i = 0; i < req->nr_segments; i++ )
+       {
+           unsigned long pfn = req->frame_and_sects[i] >> PAGE_SHIFT;
+           unsigned long mfn = phys_to_machine_mapping[pfn];
+           xen_machphys_update(mfn, pfn);
+       }
+       break;
+     }
+     
+ }
index 0000000000000000000000000000000000000000,514969cb4de285721ac2589edb88dace204fd3cd..94e12ee90b3ec6983860b087948ac7bdb681e540
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,790 +1,790 @@@
 -    cli();
+ /******************************************************************************
+  * console.c
+  * 
+  * Virtual console driver.
+  * 
+  * Copyright (c) 2002-2004, K A Fraser.
+  * 
+  * This file may be distributed separately from the Linux kernel, or
+  * incorporated into other software packages, subject to the following license:
+  * 
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+  * of this source file (the "Software"), to deal in the Software without
+  * restriction, including without limitation the rights to use, copy, modify,
+  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  * and to permit persons to whom the Software is furnished to do so, subject to
+  * the following conditions:
+  * 
+  * The above copyright notice and this permission notice shall be included in
+  * all copies or substantial portions of the Software.
+  * 
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  * IN THE SOFTWARE.
+  */
+ #include <linux/config.h>
+ #include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/errno.h>
+ #include <linux/signal.h>
+ #include <linux/sched.h>
+ #include <linux/interrupt.h>
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial.h>
+ #include <linux/major.h>
+ #include <linux/ptrace.h>
+ #include <linux/ioport.h>
+ #include <linux/mm.h>
+ #include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/console.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/uaccess.h>
+ #include <asm-xen/xen-public/event_channel.h>
+ #include <asm-xen/hypervisor.h>
+ #include <asm-xen/evtchn.h>
+ #include <asm-xen/ctrl_if.h>
+ /*
+  * Modes:
+  *  'xencons=off'  [XC_OFF]:     Console is disabled.
+  *  'xencons=tty'  [XC_TTY]:     Console attached to '/dev/tty[0-9]+'.
+  *  'xencons=ttyS' [XC_SERIAL]:  Console attached to '/dev/ttyS[0-9]+'.
+  *                 [XC_DEFAULT]: DOM0 -> XC_SERIAL ; all others -> XC_TTY.
+  * 
+  * NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses
+  * warnings from standard distro startup scripts.
+  */
+ static enum { XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL } xc_mode = XC_DEFAULT;
+ static int __init xencons_setup(char *str)
+ {
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+     if (str[0] == '=')
+       str++;
+ #endif
+     if ( !strcmp(str, "tty") )
+         xc_mode = XC_TTY;
+     else if ( !strcmp(str, "ttyS") )
+         xc_mode = XC_SERIAL;
+     else if ( !strcmp(str, "off") )
+         xc_mode = XC_OFF;
+     return 1;
+ }
+ __setup("xencons", xencons_setup);
+ /* The kernel and user-land drivers share a common transmit buffer. */
+ #define WBUF_SIZE     4096
+ #define WBUF_MASK(_i) ((_i)&(WBUF_SIZE-1))
+ static char wbuf[WBUF_SIZE];
+ static unsigned int wc, wp; /* write_cons, write_prod */
+ /* This lock protects accesses to the common transmit buffer. */
+ static spinlock_t xencons_lock = SPIN_LOCK_UNLOCKED;
+ /* Common transmit-kick routine. */
+ static void __xencons_tx_flush(void);
+ /* This task is used to defer sending console data until there is space. */
+ static void xencons_tx_flush_task_routine(void *data);
+ static DECLARE_TQUEUE(xencons_tx_flush_task, 
+                       xencons_tx_flush_task_routine,
+                       NULL);
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ static struct tty_driver *xencons_driver;
+ #else
+ static struct tty_driver xencons_driver;
+ #endif
+ /******************** Kernel console driver ********************************/
+ static void kcons_write(
+     struct console *c, const char *s, unsigned int count)
+ {
+     int           i;
+     unsigned long flags;
+     spin_lock_irqsave(&xencons_lock, flags);
+     
+     for ( i = 0; i < count; i++ )
+     {
+         if ( (wp - wc) >= (WBUF_SIZE - 1) )
+             break;
+         if ( (wbuf[WBUF_MASK(wp++)] = s[i]) == '\n' )
+             wbuf[WBUF_MASK(wp++)] = '\r';
+     }
+     __xencons_tx_flush();
+     spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+ static void kcons_write_dom0(
+     struct console *c, const char *s, unsigned int count)
+ {
+     int rc;
+     while ( count > 0 )
+     {
+         if ( (rc = HYPERVISOR_console_io(CONSOLEIO_write,
+                                          count, (char *)s)) > 0 )
+         {
+             count -= rc;
+             s += rc;
+         }
+       else
+           break;
+     }
+ }
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ static struct tty_driver *kcons_device(struct console *c, int *index)
+ {
+     *index = c->index;
+     return xencons_driver;
+ }
+ #else
+ static kdev_t kcons_device(struct console *c)
+ {
+     return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1);
+ }
+ #endif
+ static struct console kcons_info = {
+     device:  kcons_device,
+     flags:   CON_PRINTBUFFER,
+     index:   -1
+ };
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ #define __RETCODE 0
+ static int __init xen_console_init(void)
+ #else
+ #define __RETCODE
+ void xen_console_init(void)
+ #endif
+ {
+     if ( xen_start_info.flags & SIF_INITDOMAIN )
+     {
+         if ( xc_mode == XC_DEFAULT )
+             xc_mode = XC_SERIAL;
+         kcons_info.write = kcons_write_dom0;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+       if ( xc_mode == XC_SERIAL )
+           kcons_info.flags |= CON_ENABLED;
+ #endif
+     }
+     else
+     {
+         if ( xc_mode == XC_DEFAULT )
+             xc_mode = XC_TTY;
+         kcons_info.write = kcons_write;
+     }
+     if ( xc_mode == XC_OFF )
+         return __RETCODE;
+     if ( xc_mode == XC_SERIAL )
+         strcpy(kcons_info.name, "ttyS");
+     else
+         strcpy(kcons_info.name, "tty");
+     register_console(&kcons_info);
+     return __RETCODE;
+ }
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ console_initcall(xen_console_init);
+ #endif
+ /*** Useful function for console debugging -- goes straight to Xen. ***/
+ asmlinkage int xprintk(const char *fmt, ...)
+ {
+     va_list args;
+     int printk_len;
+     static char printk_buf[1024];
+     
+     /* Emit the output into the temporary buffer */
+     va_start(args, fmt);
+     printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+     va_end(args);
+     /* Send the processed output directly to Xen. */
+     kcons_write_dom0(NULL, printk_buf, printk_len);
+     return 0;
+ }
+ /*** Forcibly flush console data before dying. ***/
+ void xencons_force_flush(void)
+ {
+     ctrl_msg_t msg;
+     int        sz;
+     /* Emergency console is synchronous, so there's nothing to flush. */
+     if ( xen_start_info.flags & SIF_INITDOMAIN )
+         return;
+     /*
+      * We use dangerous control-interface functions that require a quiescent
+      * system and no interrupts. Try to ensure this with a global cli().
+      */
++    local_irq_disable();      /* XXXsmp */
+     /* Spin until console data is flushed through to the domain controller. */
+     while ( (wc != wp) && !ctrl_if_transmitter_empty() )
+     {
+         /* Interrupts are disabled -- we must manually reap responses. */
+         ctrl_if_discard_responses();
+         if ( (sz = wp - wc) == 0 )
+             continue;
+         if ( sz > sizeof(msg.msg) )
+             sz = sizeof(msg.msg);
+         if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) )
+             sz = WBUF_SIZE - WBUF_MASK(wc);
+         msg.type    = CMSG_CONSOLE;
+         msg.subtype = CMSG_CONSOLE_DATA;
+         msg.length  = sz;
+         memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
+             
+         if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
+             wc += sz;
+     }
+ }
+ /******************** User-space console driver (/dev/console) ************/
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ #define DRV(_d)         (_d)
+ #define TTY_INDEX(_tty) ((_tty)->index)
+ #else
+ static int xencons_refcount;
+ static struct tty_struct *xencons_table[MAX_NR_CONSOLES];
+ #define DRV(_d)         (&(_d))
+ #define TTY_INDEX(_tty) (MINOR((_tty)->device) - xencons_driver.minor_start)
+ #endif
+ static struct termios *xencons_termios[MAX_NR_CONSOLES];
+ static struct termios *xencons_termios_locked[MAX_NR_CONSOLES];
+ static struct tty_struct *xencons_tty;
+ static int xencons_priv_irq;
+ static char x_char;
+ /* Non-privileged receive callback. */
+ static void xencons_rx(ctrl_msg_t *msg, unsigned long id)
+ {
+     int           i;
+     unsigned long flags;
+     spin_lock_irqsave(&xencons_lock, flags);
+     if ( xencons_tty != NULL )
+     {
+         for ( i = 0; i < msg->length; i++ )
+             tty_insert_flip_char(xencons_tty, msg->msg[i], 0);
+         tty_flip_buffer_push(xencons_tty);
+     }
+     spin_unlock_irqrestore(&xencons_lock, flags);
+     msg->length = 0;
+     ctrl_if_send_response(msg);
+ }
+ /* Privileged and non-privileged transmit worker. */
+ static void __xencons_tx_flush(void)
+ {
+     int        sz, work_done = 0;
+     ctrl_msg_t msg;
+     if ( xen_start_info.flags & SIF_INITDOMAIN )
+     {
+         if ( x_char )
+         {
+             kcons_write_dom0(NULL, &x_char, 1);
+             x_char = 0;
+             work_done = 1;
+         }
+         while ( wc != wp )
+         {
+             sz = wp - wc;
+             if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) )
+                 sz = WBUF_SIZE - WBUF_MASK(wc);
+             kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
+             wc += sz;
+             work_done = 1;
+         }
+     }
+     else
+     {
+         while ( x_char )
+         {
+             msg.type    = CMSG_CONSOLE;
+             msg.subtype = CMSG_CONSOLE_DATA;
+             msg.length  = 1;
+             msg.msg[0]  = x_char;
+             if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
+                 x_char = 0;
+             else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
+                 break;
+             work_done = 1;
+         }
+         while ( wc != wp )
+         {
+             sz = wp - wc;
+             if ( sz > sizeof(msg.msg) )
+                 sz = sizeof(msg.msg);
+             if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) )
+                 sz = WBUF_SIZE - WBUF_MASK(wc);
+             msg.type    = CMSG_CONSOLE;
+             msg.subtype = CMSG_CONSOLE_DATA;
+             msg.length  = sz;
+             memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
+             
+             if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
+                 wc += sz;
+             else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
+                 break;
+             work_done = 1;
+         }
+     }
+     if ( work_done && (xencons_tty != NULL) )
+     {
+         wake_up_interruptible(&xencons_tty->write_wait);
+         if ( (xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+              (xencons_tty->ldisc.write_wakeup != NULL) )
+             (xencons_tty->ldisc.write_wakeup)(xencons_tty);
+     }
+ }
+ /* Non-privileged transmit kicker. */
+ static void xencons_tx_flush_task_routine(void *data)
+ {
+     unsigned long flags;
+     spin_lock_irqsave(&xencons_lock, flags);
+     __xencons_tx_flush();
+     spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+ /* Privileged receive callback and transmit kicker. */
+ static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id,
+                                           struct pt_regs *regs)
+ {
+     static char   rbuf[16];
+     int           i, l;
+     unsigned long flags;
+     spin_lock_irqsave(&xencons_lock, flags);
+     if ( xencons_tty != NULL )
+     {
+         /* Receive work. */
+         while ( (l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0 )
+             for ( i = 0; i < l; i++ )
+                 tty_insert_flip_char(xencons_tty, rbuf[i], 0);
+         if ( xencons_tty->flip.count != 0 )
+             tty_flip_buffer_push(xencons_tty);
+     }
+     /* Transmit work. */
+     __xencons_tx_flush();
+     spin_unlock_irqrestore(&xencons_lock, flags);
+     return IRQ_HANDLED;
+ }
+ static int xencons_write_room(struct tty_struct *tty)
+ {
+     return WBUF_SIZE - (wp - wc);
+ }
+ static int xencons_chars_in_buffer(struct tty_struct *tty)
+ {
+     return wp - wc;
+ }
+ static void xencons_send_xchar(struct tty_struct *tty, char ch)
+ {
+     unsigned long flags;
+     if ( TTY_INDEX(tty) != 0 )
+         return;
+     spin_lock_irqsave(&xencons_lock, flags);
+     x_char = ch;
+     __xencons_tx_flush();
+     spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+ static void xencons_throttle(struct tty_struct *tty)
+ {
+     if ( TTY_INDEX(tty) != 0 )
+         return;
+     if ( I_IXOFF(tty) )
+         xencons_send_xchar(tty, STOP_CHAR(tty));
+ }
+ static void xencons_unthrottle(struct tty_struct *tty)
+ {
+     if ( TTY_INDEX(tty) != 0 )
+         return;
+     if ( I_IXOFF(tty) )
+     {
+         if ( x_char != 0 )
+             x_char = 0;
+         else
+             xencons_send_xchar(tty, START_CHAR(tty));
+     }
+ }
+ static void xencons_flush_buffer(struct tty_struct *tty)
+ {
+     unsigned long flags;
+     if ( TTY_INDEX(tty) != 0 )
+         return;
+     spin_lock_irqsave(&xencons_lock, flags);
+     wc = wp = 0;
+     spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+ static inline int __xencons_put_char(int ch)
+ {
+     char _ch = (char)ch;
+     if ( (wp - wc) == WBUF_SIZE )
+         return 0;
+     wbuf[WBUF_MASK(wp++)] = _ch;
+     return 1;
+ }
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ static int xencons_write(struct tty_struct *tty, const unsigned char *buf,
+                        int count)
+ {
+     int i;
+     unsigned long flags;
+     if ( TTY_INDEX(tty) != 0 )
+         return count;
+     spin_lock_irqsave(&xencons_lock, flags);
+     for ( i = 0; i < count; i++ )
+         if ( !__xencons_put_char(buf[i]) )
+             break;
+     if ( i != 0 )
+         __xencons_tx_flush();
+     spin_unlock_irqrestore(&xencons_lock, flags);
+     return i;
+ }
+ #else
+ static int xencons_write(struct tty_struct *tty, int from_user,
+                        const u_char *buf, int count)
+ {
+     int i;
+     unsigned long flags;
+     if ( from_user && verify_area(VERIFY_READ, buf, count) )
+         return -EINVAL;
+     if ( TTY_INDEX(tty) != 0 )
+         return count;
+     spin_lock_irqsave(&xencons_lock, flags);
+     for ( i = 0; i < count; i++ )
+     {
+         char ch;
+         if ( from_user )
+             __get_user(ch, buf + i);
+         else
+             ch = buf[i];
+         if ( !__xencons_put_char(ch) )
+             break;
+     }
+     if ( i != 0 )
+         __xencons_tx_flush();
+     spin_unlock_irqrestore(&xencons_lock, flags);
+     return i;
+ }
+ #endif
+ static void xencons_put_char(struct tty_struct *tty, u_char ch)
+ {
+     unsigned long flags;
+     if ( TTY_INDEX(tty) != 0 )
+         return;
+     spin_lock_irqsave(&xencons_lock, flags);
+     (void)__xencons_put_char(ch);
+     spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+ static void xencons_flush_chars(struct tty_struct *tty)
+ {
+     unsigned long flags;
+     if ( TTY_INDEX(tty) != 0 )
+         return;
+     spin_lock_irqsave(&xencons_lock, flags);
+     __xencons_tx_flush();
+     spin_unlock_irqrestore(&xencons_lock, flags);    
+ }
+ static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
+ {
+     unsigned long orig_jiffies = jiffies;
+     if ( TTY_INDEX(tty) != 0 )
+         return;
+     while ( DRV(tty->driver)->chars_in_buffer(tty) )
+     {
+         set_current_state(TASK_INTERRUPTIBLE);
+         schedule_timeout(1);
+         if ( signal_pending(current) )
+             break;
+         if ( (timeout != 0) && time_after(jiffies, orig_jiffies + timeout) )
+             break;
+     }
+     
+     set_current_state(TASK_RUNNING);
+ }
+ static int xencons_open(struct tty_struct *tty, struct file *filp)
+ {
+     unsigned long flags;
+     if ( TTY_INDEX(tty) != 0 )
+         return 0;
+     spin_lock_irqsave(&xencons_lock, flags);
+     tty->driver_data = NULL;
+     if ( xencons_tty == NULL )
+         xencons_tty = tty;
+     __xencons_tx_flush();
+     spin_unlock_irqrestore(&xencons_lock, flags);    
+     return 0;
+ }
+ static void xencons_close(struct tty_struct *tty, struct file *filp)
+ {
+     unsigned long flags;
+     if ( TTY_INDEX(tty) != 0 )
+         return;
+     if ( tty->count == 1 )
+     {
+         tty->closing = 1;
+         tty_wait_until_sent(tty, 0);
+         if ( DRV(tty->driver)->flush_buffer != NULL )
+             DRV(tty->driver)->flush_buffer(tty);
+         if ( tty->ldisc.flush_buffer != NULL )
+             tty->ldisc.flush_buffer(tty);
+         tty->closing = 0;
+         spin_lock_irqsave(&xencons_lock, flags);
+         xencons_tty = NULL;
+         spin_unlock_irqrestore(&xencons_lock, flags);    
+     }
+ }
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ static struct tty_operations xencons_ops = {
+     .open = xencons_open,
+     .close = xencons_close,
+     .write = xencons_write,
+     .write_room = xencons_write_room,
+     .put_char = xencons_put_char,
+     .flush_chars = xencons_flush_chars,
+     .chars_in_buffer = xencons_chars_in_buffer,
+     .send_xchar = xencons_send_xchar,
+     .flush_buffer = xencons_flush_buffer,
+     .throttle = xencons_throttle,
+     .unthrottle = xencons_unthrottle,
+     .wait_until_sent = xencons_wait_until_sent,
+ };
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ static const char *xennullcon_startup(void)
+ {
+     return NULL;
+ }
+ static int xennullcon_dummy(void)
+ {
+     return 0;
+ }
+ #define DUMMY (void *)xennullcon_dummy
+ /*
+  *  The console `switch' structure for the dummy console
+  *
+  *  Most of the operations are dummies.
+  */
+ const struct consw xennull_con = {
+     .owner =          THIS_MODULE,
+     .con_startup =    xennullcon_startup,
+     .con_init =               DUMMY,
+     .con_deinit =     DUMMY,
+     .con_clear =      DUMMY,
+     .con_putc =               DUMMY,
+     .con_putcs =      DUMMY,
+     .con_cursor =     DUMMY,
+     .con_scroll =     DUMMY,
+     .con_bmove =      DUMMY,
+     .con_switch =     DUMMY,
+     .con_blank =      DUMMY,
+     .con_font_set =   DUMMY,
+     .con_font_get =   DUMMY,
+     .con_font_default =       DUMMY,
+     .con_font_copy =  DUMMY,
+     .con_set_palette =        DUMMY,
+     .con_scrolldelta =        DUMMY,
+ };
+ #endif
+ #endif
+ static int __init xencons_init(void)
+ {
+     int rc;
+     if ( xc_mode == XC_OFF )
+         return 0;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+     xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ? 
+                                       1 : MAX_NR_CONSOLES);
+     if ( xencons_driver == NULL )
+         return -ENOMEM;
+ #else
+     memset(&xencons_driver, 0, sizeof(struct tty_driver));
+     xencons_driver.magic       = TTY_DRIVER_MAGIC;
+     xencons_driver.refcount    = &xencons_refcount;
+     xencons_driver.table       = xencons_table;
+     xencons_driver.num         = (xc_mode == XC_SERIAL) ? 1 : MAX_NR_CONSOLES;
+ #endif
+     DRV(xencons_driver)->major           = TTY_MAJOR;
+     DRV(xencons_driver)->type            = TTY_DRIVER_TYPE_SERIAL;
+     DRV(xencons_driver)->subtype         = SERIAL_TYPE_NORMAL;
+     DRV(xencons_driver)->init_termios    = tty_std_termios;
+     DRV(xencons_driver)->flags           = 
+         TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS;
+     DRV(xencons_driver)->termios         = xencons_termios;
+     DRV(xencons_driver)->termios_locked  = xencons_termios_locked;
+     if ( xc_mode == XC_SERIAL )
+     {
+         DRV(xencons_driver)->name        = "ttyS";
+         DRV(xencons_driver)->minor_start = 64;
+       DRV(xencons_driver)->name_base   = 0;
+     }
+     else
+     {
+         DRV(xencons_driver)->name        = "tty";
+         DRV(xencons_driver)->minor_start = 1;
+       DRV(xencons_driver)->name_base   = 1;
+     }
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+     tty_set_operations(xencons_driver, &xencons_ops);
+ #else
+     xencons_driver.open            = xencons_open;
+     xencons_driver.close           = xencons_close;
+     xencons_driver.write           = xencons_write;
+     xencons_driver.write_room      = xencons_write_room;
+     xencons_driver.put_char        = xencons_put_char;
+     xencons_driver.flush_chars     = xencons_flush_chars;
+     xencons_driver.chars_in_buffer = xencons_chars_in_buffer;
+     xencons_driver.send_xchar      = xencons_send_xchar;
+     xencons_driver.flush_buffer    = xencons_flush_buffer;
+     xencons_driver.throttle        = xencons_throttle;
+     xencons_driver.unthrottle      = xencons_unthrottle;
+     xencons_driver.wait_until_sent = xencons_wait_until_sent;
+ #endif
+     if ( (rc = tty_register_driver(DRV(xencons_driver))) != 0 )
+     {
+         printk("Couldn't register Xen virtual console driver as %s\n",
+                DRV(xencons_driver)->name);
+         return rc;
+     }
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+     tty_register_device(xencons_driver, 0, NULL);
+ #endif
+     if ( xen_start_info.flags & SIF_INITDOMAIN )
+     {
+         xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
+         (void)request_irq(xencons_priv_irq,
+                           xencons_priv_interrupt, 0, "console", NULL);
+     }
+     else
+     {
+         (void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0);
+     }
+     printk("Xen virtual console successfully installed as %s\n",
+            DRV(xencons_driver)->name);
+     
+     return 0;
+ }
+ static void __exit xencons_fini(void)
+ {
+     int ret;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+     tty_unregister_device(xencons_driver, 0);
+ #endif
+     if ( (ret = tty_unregister_driver(DRV(xencons_driver))) != 0 )
+         printk(KERN_ERR "Unable to unregister Xen console driver: %d\n", ret);
+     if ( xen_start_info.flags & SIF_INITDOMAIN )
+     {
+         free_irq(xencons_priv_irq, NULL);
+         unbind_virq_from_irq(VIRQ_CONSOLE);
+     }
+     else
+     {
+         ctrl_if_unregister_receiver(CMSG_CONSOLE, xencons_rx);
+     }
+ }
+ module_init(xencons_init);
+ module_exit(xencons_fini);
index 0000000000000000000000000000000000000000,97d229001d48d7c038c61e32c31bb01407844b46..165120b40100c16acb9761d750cda1270a7f3cec
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,429 +1,430 @@@
+ /******************************************************************************
+  * evtchn.c
+  * 
+  * Xenolinux driver for receiving and demuxing event-channel signals.
+  * 
+  * Copyright (c) 2004, K A Fraser
+  * Multi-process extensions Copyright (c) 2004, Steven Smith
+  * 
+  * This file may be distributed separately from the Linux kernel, or
+  * incorporated into other software packages, subject to the following license:
+  * 
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+  * of this source file (the "Software"), to deal in the Software without
+  * restriction, including without limitation the rights to use, copy, modify,
+  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  * and to permit persons to whom the Software is furnished to do so, subject to
+  * the following conditions:
+  * 
+  * The above copyright notice and this permission notice shall be included in
+  * all copies or substantial portions of the Software.
+  * 
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  * IN THE SOFTWARE.
+  */
+ #include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/errno.h>
+ #include <linux/fs.h>
+ #include <linux/errno.h>
+ #include <linux/miscdevice.h>
+ #include <linux/major.h>
+ #include <linux/proc_fs.h>
+ #include <linux/stat.h>
+ #include <linux/poll.h>
+ #include <linux/irq.h>
+ #include <linux/init.h>
++#define XEN_EVTCHN_MASK_OPS
+ #include <asm-xen/evtchn.h>
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ #include <linux/devfs_fs_kernel.h>
+ #define OLD_DEVFS
+ #else
+ #include <linux/gfp.h>
+ #endif
+ #ifdef OLD_DEVFS
+ /* NB. This must be shared amongst drivers if more things go in /dev/xen */
+ static devfs_handle_t xen_dev_dir;
+ #endif
+ struct per_user_data {
+     /* Notification ring, accessed via /dev/xen/evtchn. */
+ #   define RING_SIZE     2048  /* 2048 16-bit entries */
+ #   define RING_MASK(_i) ((_i)&(RING_SIZE-1))
+     u16 *ring;
+     unsigned int ring_cons, ring_prod, ring_overflow;
+     /* Processes wait on this queue when ring is empty. */
+     wait_queue_head_t evtchn_wait;
+     struct fasync_struct *evtchn_async_queue;
+ };
+ /* Who's bound to each port? */
+ static struct per_user_data *port_user[NR_EVENT_CHANNELS];
+ static spinlock_t port_user_lock;
+ void evtchn_device_upcall(int port)
+ {
+     struct per_user_data *u;
+     spin_lock(&port_user_lock);
+     mask_evtchn(port);
+     clear_evtchn(port);
+     if ( (u = port_user[port]) != NULL )
+     {
+         if ( (u->ring_prod - u->ring_cons) < RING_SIZE )
+         {
+             u->ring[RING_MASK(u->ring_prod)] = (u16)port;
+             if ( u->ring_cons == u->ring_prod++ )
+             {
+                 wake_up_interruptible(&u->evtchn_wait);
+                 kill_fasync(&u->evtchn_async_queue, SIGIO, POLL_IN);
+             }
+         }
+         else
+         {
+             u->ring_overflow = 1;
+         }
+     }
+     spin_unlock(&port_user_lock);
+ }
+ static ssize_t evtchn_read(struct file *file, char *buf,
+                            size_t count, loff_t *ppos)
+ {
+     int rc;
+     unsigned int c, p, bytes1 = 0, bytes2 = 0;
+     DECLARE_WAITQUEUE(wait, current);
+     struct per_user_data *u = file->private_data;
+     add_wait_queue(&u->evtchn_wait, &wait);
+     count &= ~1; /* even number of bytes */
+     if ( count == 0 )
+     {
+         rc = 0;
+         goto out;
+     }
+     if ( count > PAGE_SIZE )
+         count = PAGE_SIZE;
+     for ( ; ; )
+     {
+         set_current_state(TASK_INTERRUPTIBLE);
+         if ( (c = u->ring_cons) != (p = u->ring_prod) )
+             break;
+         if ( u->ring_overflow )
+         {
+             rc = -EFBIG;
+             goto out;
+         }
+         if ( file->f_flags & O_NONBLOCK )
+         {
+             rc = -EAGAIN;
+             goto out;
+         }
+         if ( signal_pending(current) )
+         {
+             rc = -ERESTARTSYS;
+             goto out;
+         }
+         schedule();
+     }
+     /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
+     if ( ((c ^ p) & RING_SIZE) != 0 )
+     {
+         bytes1 = (RING_SIZE - RING_MASK(c)) * sizeof(u16);
+         bytes2 = RING_MASK(p) * sizeof(u16);
+     }
+     else
+     {
+         bytes1 = (p - c) * sizeof(u16);
+         bytes2 = 0;
+     }
+     /* Truncate chunks according to caller's maximum byte count. */
+     if ( bytes1 > count )
+     {
+         bytes1 = count;
+         bytes2 = 0;
+     }
+     else if ( (bytes1 + bytes2) > count )
+     {
+         bytes2 = count - bytes1;
+     }
+     if ( copy_to_user(buf, &u->ring[RING_MASK(c)], bytes1) ||
+          ((bytes2 != 0) && copy_to_user(&buf[bytes1], &u->ring[0], bytes2)) )
+     {
+         rc = -EFAULT;
+         goto out;
+     }
+     u->ring_cons += (bytes1 + bytes2) / sizeof(u16);
+     rc = bytes1 + bytes2;
+  out:
+     __set_current_state(TASK_RUNNING);
+     remove_wait_queue(&u->evtchn_wait, &wait);
+     return rc;
+ }
+ static ssize_t evtchn_write(struct file *file, const char *buf,
+                             size_t count, loff_t *ppos)
+ {
+     int  rc, i;
+     u16 *kbuf = (u16 *)__get_free_page(GFP_KERNEL);
+     struct per_user_data *u = file->private_data;
+     if ( kbuf == NULL )
+         return -ENOMEM;
+     count &= ~1; /* even number of bytes */
+     if ( count == 0 )
+     {
+         rc = 0;
+         goto out;
+     }
+     if ( count > PAGE_SIZE )
+         count = PAGE_SIZE;
+     if ( copy_from_user(kbuf, buf, count) != 0 )
+     {
+         rc = -EFAULT;
+         goto out;
+     }
+     spin_lock_irq(&port_user_lock);
+     for ( i = 0; i < (count/2); i++ )
+         if ( (kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u) )
+             unmask_evtchn(kbuf[i]);
+     spin_unlock_irq(&port_user_lock);
+     rc = count;
+  out:
+     free_page((unsigned long)kbuf);
+     return rc;
+ }
+ static int evtchn_ioctl(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg)
+ {
+     int rc = 0;
+     struct per_user_data *u = file->private_data;
+     spin_lock_irq(&port_user_lock);
+     
+     switch ( cmd )
+     {
+     case EVTCHN_RESET:
+         /* Initialise the ring to empty. Clear errors. */
+         u->ring_cons = u->ring_prod = u->ring_overflow = 0;
+         break;
+     case EVTCHN_BIND:
+         if ( arg >= NR_EVENT_CHANNELS )
+         {
+             rc = -EINVAL;
+         }
+         else if ( port_user[arg] != NULL )
+         {
+             rc = -EISCONN;
+         }
+         else
+         {
+             port_user[arg] = u;
+             unmask_evtchn(arg);
+         }
+         break;
+     case EVTCHN_UNBIND:
+         if ( arg >= NR_EVENT_CHANNELS )
+         {
+             rc = -EINVAL;
+         }
+         else if ( port_user[arg] != u )
+         {
+             rc = -ENOTCONN;
+         }
+         else
+         {
+             port_user[arg] = NULL;
+             mask_evtchn(arg);
+         }
+         break;
+     default:
+         rc = -ENOSYS;
+         break;
+     }
+     spin_unlock_irq(&port_user_lock);   
+     return rc;
+ }
+ static unsigned int evtchn_poll(struct file *file, poll_table *wait)
+ {
+     unsigned int mask = POLLOUT | POLLWRNORM;
+     struct per_user_data *u = file->private_data;
+     poll_wait(file, &u->evtchn_wait, wait);
+     if ( u->ring_cons != u->ring_prod )
+         mask |= POLLIN | POLLRDNORM;
+     if ( u->ring_overflow )
+         mask = POLLERR;
+     return mask;
+ }
+ static int evtchn_fasync(int fd, struct file *filp, int on)
+ {
+     struct per_user_data *u = filp->private_data;
+     return fasync_helper(fd, filp, on, &u->evtchn_async_queue);
+ }
+ static int evtchn_open(struct inode *inode, struct file *filp)
+ {
+     struct per_user_data *u;
+     if ( (u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL )
+         return -ENOMEM;
+     memset(u, 0, sizeof(*u));
+     init_waitqueue_head(&u->evtchn_wait);
+     if ( (u->ring = (u16 *)__get_free_page(GFP_KERNEL)) == NULL )
+     {
+         kfree(u);
+         return -ENOMEM;
+     }
+     filp->private_data = u;
+     return 0;
+ }
+ static int evtchn_release(struct inode *inode, struct file *filp)
+ {
+     int i;
+     struct per_user_data *u = filp->private_data;
+     spin_lock_irq(&port_user_lock);
+     free_page((unsigned long)u->ring);
+     for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
+     {
+         if ( port_user[i] == u )
+         {
+             port_user[i] = NULL;
+             mask_evtchn(i);
+         }
+     }
+     spin_unlock_irq(&port_user_lock);
+     return 0;
+ }
+ static struct file_operations evtchn_fops = {
+     owner:    THIS_MODULE,
+     read:     evtchn_read,
+     write:    evtchn_write,
+     ioctl:    evtchn_ioctl,
+     poll:     evtchn_poll,
+     fasync:   evtchn_fasync,
+     open:     evtchn_open,
+     release:  evtchn_release
+ };
+ static struct miscdevice evtchn_miscdev = {
+     .minor        = EVTCHN_MINOR,
+     .name         = "evtchn",
+     .fops         = &evtchn_fops,
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+     .devfs_name   = "misc/evtchn",
+ #endif
+ };
+ static int __init evtchn_init(void)
+ {
+ #ifdef OLD_DEVFS
+     devfs_handle_t symlink_handle;
+     int            pos;
+     char           link_dest[64];
+ #endif
+     int err;
+     spin_lock_init(&port_user_lock);
+     memset(port_user, 0, sizeof(port_user));
+     /* (DEVFS) create '/dev/misc/evtchn'. */
+     err = misc_register(&evtchn_miscdev);
+     if ( err != 0 )
+     {
+         printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
+         return err;
+     }
+ #ifdef OLD_DEVFS
+     /* (DEVFS) create directory '/dev/xen'. */
+     xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
+     /* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
+     pos = devfs_generate_path(evtchn_miscdev.devfs_handle, 
+                               &link_dest[3], 
+                               sizeof(link_dest) - 3);
+     if ( pos >= 0 )
+         strncpy(&link_dest[pos], "../", 3);
+     /* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
+     (void)devfs_mk_symlink(xen_dev_dir, 
+                            "evtchn", 
+                            DEVFS_FL_DEFAULT, 
+                            &link_dest[pos],
+                            &symlink_handle, 
+                            NULL);
+     /* (DEVFS) automatically destroy the symlink with its destination. */
+     devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
+ #endif
+     printk("Event-channel device installed.\n");
+     return 0;
+ }
+ static void evtchn_cleanup(void)
+ {
+     misc_deregister(&evtchn_miscdev);
+ }
+ module_init(evtchn_init);
+ module_exit(evtchn_cleanup);
index 0000000000000000000000000000000000000000,41d947bacfbc1204e575fccfd0901276365f3a58..0faf0a61b709066930ba27a7302b01bb1edebd98
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,838 +1,839 @@@
+ /******************************************************************************
+  * arch/xen/drivers/netif/backend/main.c
+  * 
+  * Back-end of the driver for virtual block devices. This portion of the
+  * driver exports a 'unified' block-device interface that can be accessed
+  * by any operating system that implements a compatible front end. A 
+  * reference front-end implementation can be found in:
+  *  arch/xen/drivers/netif/frontend
+  * 
+  * Copyright (c) 2002-2004, K A Fraser
+  */
+ #include "common.h"
+ #include <asm-xen/balloon.h>
++#include <asm-xen/evtchn.h>
+ static void netif_page_release(struct page *page);
+ static void netif_skb_release(struct sk_buff *skb);
+ static void make_tx_response(netif_t *netif, 
+                              u16      id,
+                              s8       st);
+ static int  make_rx_response(netif_t *netif, 
+                              u16      id, 
+                              s8       st,
+                              memory_t addr,
+                              u16      size);
+ static void net_tx_action(unsigned long unused);
+ static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
+ static void net_rx_action(unsigned long unused);
+ static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0);
+ static struct timer_list net_timer;
+ static struct sk_buff_head rx_queue;
+ static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2];
+ static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE*3];
+ static unsigned char rx_notify[NR_EVENT_CHANNELS];
+ /* Don't currently gate addition of an interface to the tx scheduling list. */
+ #define tx_work_exists(_if) (1)
+ #define MAX_PENDING_REQS 256
+ static unsigned long mmap_vstart;
+ #define MMAP_VADDR(_req) (mmap_vstart + ((_req) * PAGE_SIZE))
+ #define PKT_PROT_LEN 64
+ static struct {
+     netif_tx_request_t req;
+     netif_t *netif;
+ } pending_tx_info[MAX_PENDING_REQS];
+ static u16 pending_ring[MAX_PENDING_REQS];
+ typedef unsigned int PEND_RING_IDX;
+ #define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
+ static PEND_RING_IDX pending_prod, pending_cons;
+ #define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
+ /* Freed TX SKBs get batched on this ring before return to pending_ring. */
+ static u16 dealloc_ring[MAX_PENDING_REQS];
+ static spinlock_t dealloc_lock = SPIN_LOCK_UNLOCKED;
+ static PEND_RING_IDX dealloc_prod, dealloc_cons;
+ static struct sk_buff_head tx_queue;
+ static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
+ static struct list_head net_schedule_list;
+ static spinlock_t net_schedule_list_lock;
+ #define MAX_MFN_ALLOC 64
+ static unsigned long mfn_list[MAX_MFN_ALLOC];
+ static unsigned int alloc_index = 0;
+ static spinlock_t mfn_lock = SPIN_LOCK_UNLOCKED;
+ static unsigned long alloc_mfn(void)
+ {
+     unsigned long mfn = 0, flags;
+     spin_lock_irqsave(&mfn_lock, flags);
+     if ( unlikely(alloc_index == 0) )
+         alloc_index = HYPERVISOR_dom_mem_op(
+             MEMOP_increase_reservation, mfn_list, MAX_MFN_ALLOC, 0);
+     if ( alloc_index != 0 )
+         mfn = mfn_list[--alloc_index];
+     spin_unlock_irqrestore(&mfn_lock, flags);
+     return mfn;
+ }
+ static void free_mfn(unsigned long mfn)
+ {
+     unsigned long flags;
+     spin_lock_irqsave(&mfn_lock, flags);
+     if ( alloc_index != MAX_MFN_ALLOC )
+         mfn_list[alloc_index++] = mfn;
+     else if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation,
+                                     &mfn, 1, 0) != 1 )
+         BUG();
+     spin_unlock_irqrestore(&mfn_lock, flags);
+ }
+ static inline void maybe_schedule_tx_action(void)
+ {
+     smp_mb();
+     if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+          !list_empty(&net_schedule_list) )
+         tasklet_schedule(&net_tx_tasklet);
+ }
+ /*
+  * A gross way of confirming the origin of an skb data page. The slab
+  * allocator abuses a field in the page struct to cache the kmem_cache_t ptr.
+  */
+ static inline int is_xen_skb(struct sk_buff *skb)
+ {
+     extern kmem_cache_t *skbuff_cachep;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+     kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->lru.next;
+ #else
+     kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->list.next;
+ #endif
+     return (cp == skbuff_cachep);
+ }
+ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+     netif_t *netif = (netif_t *)dev->priv;
+     ASSERT(skb->dev == dev);
+     /* Drop the packet if the target domain has no receive buffers. */
+     if ( (netif->rx_req_cons == netif->rx->req_prod) ||
+          ((netif->rx_req_cons-netif->rx_resp_prod) == NETIF_RX_RING_SIZE) )
+         goto drop;
+     /*
+      * We do not copy the packet unless:
+      *  1. The data is shared; or
+      *  2. The data is not allocated from our special cache.
+      * NB. We also couldn't cope with fragmented packets, but we won't get
+      *     any because we not advertise the NETIF_F_SG feature.
+      */
+     if ( skb_shared(skb) || skb_cloned(skb) || !is_xen_skb(skb) )
+     {
+         int hlen = skb->data - skb->head;
+         struct sk_buff *nskb = dev_alloc_skb(hlen + skb->len);
+         if ( unlikely(nskb == NULL) )
+             goto drop;
+         skb_reserve(nskb, hlen);
+         __skb_put(nskb, skb->len);
+         (void)skb_copy_bits(skb, -hlen, nskb->data - hlen, skb->len + hlen);
+         nskb->dev = skb->dev;
+         dev_kfree_skb(skb);
+         skb = nskb;
+     }
+     netif->rx_req_cons++;
+     skb_queue_tail(&rx_queue, skb);
+     tasklet_schedule(&net_rx_tasklet);
+     return 0;
+  drop:
+     netif->stats.tx_dropped++;
+     dev_kfree_skb(skb);
+     return 0;
+ }
+ #if 0
+ static void xen_network_done_notify(void)
+ {
+     static struct net_device *eth0_dev = NULL;
+     if ( unlikely(eth0_dev == NULL) )
+         eth0_dev = __dev_get_by_name("eth0");
+     netif_rx_schedule(eth0_dev);
+ }
+ /* 
+  * Add following to poll() function in NAPI driver (Tigon3 is example):
+  *  if ( xen_network_done() )
+  *      tg3_enable_ints(tp); 
+  */
+ int xen_network_done(void)
+ {
+     return skb_queue_empty(&rx_queue);
+ }
+ #endif
+ static void net_rx_action(unsigned long unused)
+ {
+     netif_t *netif;
+     s8 status;
+     u16 size, id, evtchn;
+     mmu_update_t *mmu;
+     multicall_entry_t *mcl;
+     unsigned long vdata, mdata, new_mfn;
+     struct sk_buff_head rxq;
+     struct sk_buff *skb;
+     u16 notify_list[NETIF_RX_RING_SIZE];
+     int notify_nr = 0;
+     skb_queue_head_init(&rxq);
+     mcl = rx_mcl;
+     mmu = rx_mmu;
+     while ( (skb = skb_dequeue(&rx_queue)) != NULL )
+     {
+         netif   = (netif_t *)skb->dev->priv;
+         vdata   = (unsigned long)skb->data;
+         mdata   = virt_to_machine(vdata);
+         /* Memory squeeze? Back off for an arbitrary while. */
+         if ( (new_mfn = alloc_mfn()) == 0 )
+         {
+             if ( net_ratelimit() )
+                 printk(KERN_WARNING "Memory squeeze in netback driver.\n");
+             mod_timer(&net_timer, jiffies + HZ);
+             break;
+         }
+         /*
+          * Set the new P2M table entry before reassigning the old data page.
+          * Heed the comment in pgtable-2level.h:pte_page(). :-)
+          */
+         phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = new_mfn;
+         
+         mmu[0].ptr  = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+         mmu[0].val  = __pa(vdata) >> PAGE_SHIFT;  
+         mmu[1].ptr  = MMU_EXTENDED_COMMAND;
+         mmu[1].val  = MMUEXT_SET_FOREIGNDOM;      
+         mmu[1].val |= (unsigned long)netif->domid << 16;
+         mmu[2].ptr  = (mdata & PAGE_MASK) | MMU_EXTENDED_COMMAND;
+         mmu[2].val  = MMUEXT_REASSIGN_PAGE;
+         mcl[0].op = __HYPERVISOR_update_va_mapping;
+         mcl[0].args[0] = vdata >> PAGE_SHIFT;
+         mcl[0].args[1] = (new_mfn << PAGE_SHIFT) | __PAGE_KERNEL;
+         mcl[0].args[2] = 0;
+         mcl[1].op = __HYPERVISOR_mmu_update;
+         mcl[1].args[0] = (unsigned long)mmu;
+         mcl[1].args[1] = 3;
+         mcl[1].args[2] = 0;
+         mcl += 2;
+         mmu += 3;
+         __skb_queue_tail(&rxq, skb);
+         /* Filled the batch queue? */
+         if ( (mcl - rx_mcl) == ARRAY_SIZE(rx_mcl) )
+             break;
+     }
+     if ( mcl == rx_mcl )
+         return;
+     mcl[-2].args[2] = UVMF_FLUSH_TLB;
+     if ( unlikely(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0) )
+         BUG();
+     mcl = rx_mcl;
+     mmu = rx_mmu;
+     while ( (skb = __skb_dequeue(&rxq)) != NULL )
+     {
+         netif   = (netif_t *)skb->dev->priv;
+         size    = skb->tail - skb->data;
+         /* Rederive the machine addresses. */
+         new_mfn = mcl[0].args[1] >> PAGE_SHIFT;
+         mdata   = ((mmu[2].ptr & PAGE_MASK) |
+                    ((unsigned long)skb->data & ~PAGE_MASK));
+         
+         atomic_set(&(skb_shinfo(skb)->dataref), 1);
+         skb_shinfo(skb)->nr_frags = 0;
+         skb_shinfo(skb)->frag_list = NULL;
+         netif->stats.tx_bytes += size;
+         netif->stats.tx_packets++;
+         /* The update_va_mapping() must not fail. */
+         if ( unlikely(mcl[0].args[5] != 0) )
+             BUG();
+         /* Check the reassignment error code. */
+         status = NETIF_RSP_OKAY;
+         if ( unlikely(mcl[1].args[5] != 0) )
+         {
+             DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid);
+             free_mfn(mdata >> PAGE_SHIFT);
+             status = NETIF_RSP_ERROR;
+         }
+         evtchn = netif->evtchn;
+         id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id;
+         if ( make_rx_response(netif, id, status, mdata, size) &&
+              (rx_notify[evtchn] == 0) )
+         {
+             rx_notify[evtchn] = 1;
+             notify_list[notify_nr++] = evtchn;
+         }
+         dev_kfree_skb(skb);
+         mcl += 2;
+         mmu += 3;
+     }
+     while ( notify_nr != 0 )
+     {
+         evtchn = notify_list[--notify_nr];
+         rx_notify[evtchn] = 0;
+         notify_via_evtchn(evtchn);
+     }
+     /* More work to do? */
+     if ( !skb_queue_empty(&rx_queue) && !timer_pending(&net_timer) )
+         tasklet_schedule(&net_rx_tasklet);
+ #if 0
+     else
+         xen_network_done_notify();
+ #endif
+ }
+ static void net_alarm(unsigned long unused)
+ {
+     tasklet_schedule(&net_rx_tasklet);
+ }
+ struct net_device_stats *netif_be_get_stats(struct net_device *dev)
+ {
+     netif_t *netif = dev->priv;
+     return &netif->stats;
+ }
+ static int __on_net_schedule_list(netif_t *netif)
+ {
+     return netif->list.next != NULL;
+ }
+ static void remove_from_net_schedule_list(netif_t *netif)
+ {
+     spin_lock_irq(&net_schedule_list_lock);
+     if ( likely(__on_net_schedule_list(netif)) )
+     {
+         list_del(&netif->list);
+         netif->list.next = NULL;
+         netif_put(netif);
+     }
+     spin_unlock_irq(&net_schedule_list_lock);
+ }
+ static void add_to_net_schedule_list_tail(netif_t *netif)
+ {
+     if ( __on_net_schedule_list(netif) )
+         return;
+     spin_lock_irq(&net_schedule_list_lock);
+     if ( !__on_net_schedule_list(netif) && (netif->status == CONNECTED) )
+     {
+         list_add_tail(&netif->list, &net_schedule_list);
+         netif_get(netif);
+     }
+     spin_unlock_irq(&net_schedule_list_lock);
+ }
+ static inline void netif_schedule_work(netif_t *netif)
+ {
+     if ( (netif->tx_req_cons != netif->tx->req_prod) &&
+          ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE) )
+     {
+         add_to_net_schedule_list_tail(netif);
+         maybe_schedule_tx_action();
+     }
+ }
+ void netif_deschedule(netif_t *netif)
+ {
+     remove_from_net_schedule_list(netif);
+ }
+ #if 0
+ static void tx_credit_callback(unsigned long data)
+ {
+     netif_t *netif = (netif_t *)data;
+     netif->remaining_credit = netif->credit_bytes;
+     netif_schedule_work(netif);
+ }
+ #endif
+ static void net_tx_action(unsigned long unused)
+ {
+     struct list_head *ent;
+     struct sk_buff *skb;
+     netif_t *netif;
+     netif_tx_request_t txreq;
+     u16 pending_idx;
+     NETIF_RING_IDX i;
+     multicall_entry_t *mcl;
+     PEND_RING_IDX dc, dp;
+     unsigned int data_len;
+     if ( (dc = dealloc_cons) == (dp = dealloc_prod) )
+         goto skip_dealloc;
+     mcl = tx_mcl;
+     while ( dc != dp )
+     {
+         pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
+         mcl[0].op = __HYPERVISOR_update_va_mapping;
+         mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
+         mcl[0].args[1] = 0;
+         mcl[0].args[2] = 0;
+         mcl++;        
+     }
+     mcl[-1].args[2] = UVMF_FLUSH_TLB;
+     if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) )
+         BUG();
+     mcl = tx_mcl;
+     while ( dealloc_cons != dp )
+     {
+         /* The update_va_mapping() must not fail. */
+         if ( unlikely(mcl[0].args[5] != 0) )
+             BUG();
+         pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)];
+         netif = pending_tx_info[pending_idx].netif;
+         spin_lock(&netif->tx_lock);
+         make_tx_response(netif, pending_tx_info[pending_idx].req.id, 
+                          NETIF_RSP_OKAY);
+         spin_unlock(&netif->tx_lock);
+         
+         pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+         /*
+          * Scheduling checks must happen after the above response is posted.
+          * This avoids a possible race with a guest OS on another CPU if that
+          * guest is testing against 'resp_prod' when deciding whether to notify
+          * us when it queues additional packets.
+          */
+         mb();
+         if ( (netif->tx_req_cons != netif->tx->req_prod) &&
+              ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE) )
+             add_to_net_schedule_list_tail(netif);
+         
+         netif_put(netif);
+         mcl++;
+     }
+  skip_dealloc:
+     mcl = tx_mcl;
+     while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
+             !list_empty(&net_schedule_list) )
+     {
+         /* Get a netif from the list with work to do. */
+         ent = net_schedule_list.next;
+         netif = list_entry(ent, netif_t, list);
+         netif_get(netif);
+         remove_from_net_schedule_list(netif);
+         /* Work to do? */
+         i = netif->tx_req_cons;
+         if ( (i == netif->tx->req_prod) ||
+              ((i-netif->tx_resp_prod) == NETIF_TX_RING_SIZE) )
+         {
+             netif_put(netif);
+             continue;
+         }
+         netif->tx->req_cons = ++netif->tx_req_cons;
+         /*
+          * 1. Ensure that we see the request when we copy it.
+          * 2. Ensure that frontend sees updated req_cons before we check
+          *    for more work to schedule.
+          */
+         mb();
+         memcpy(&txreq, &netif->tx->ring[MASK_NETIF_TX_IDX(i)].req, 
+                sizeof(txreq));
+ #if 0
+         /* Credit-based scheduling. */
+         if ( tx.size > netif->remaining_credit )
+         {
+             s_time_t now = NOW(), next_credit = 
+                 netif->credit_timeout.expires + MICROSECS(netif->credit_usec);
+             if ( next_credit <= now )
+             {
+                 netif->credit_timeout.expires = now;
+                 netif->remaining_credit = netif->credit_bytes;
+             }
+             else
+             {
+                 netif->remaining_credit = 0;
+                 netif->credit_timeout.expires  = next_credit;
+                 netif->credit_timeout.data     = (unsigned long)netif;
+                 netif->credit_timeout.function = tx_credit_callback;
+                 netif->credit_timeout.cpu      = smp_processor_id();
+                 add_ac_timer(&netif->credit_timeout);
+                 break;
+             }
+         }
+         netif->remaining_credit -= tx.size;
+ #endif
+         netif_schedule_work(netif);
+         if ( unlikely(txreq.size < ETH_HLEN) || 
+              unlikely(txreq.size > ETH_FRAME_LEN) )
+         {
+             DPRINTK("Bad packet size: %d\n", txreq.size);
+             make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
+             netif_put(netif);
+             continue; 
+         }
+         /* No crossing a page boundary as the payload mustn't fragment. */
+         if ( unlikely(((txreq.addr & ~PAGE_MASK) + txreq.size) >= PAGE_SIZE) ) 
+         {
+             DPRINTK("txreq.addr: %lx, size: %u, end: %lu\n", 
+                     txreq.addr, txreq.size, 
+                     (txreq.addr &~PAGE_MASK) + txreq.size);
+             make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
+             netif_put(netif);
+             continue;
+         }
+         pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+         data_len = txreq.size > PKT_PROT_LEN ? PKT_PROT_LEN : txreq.size;
+         if ( unlikely((skb = alloc_skb(data_len+16, GFP_ATOMIC)) == NULL) )
+         {
+             DPRINTK("Can't allocate a skb in start_xmit.\n");
+             make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
+             netif_put(netif);
+             break;
+         }
+         /* Packets passed to netif_rx() must have some headroom. */
+         skb_reserve(skb, 16);
+         mcl[0].op = __HYPERVISOR_update_va_mapping_otherdomain;
+         mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
+         mcl[0].args[1] = (txreq.addr & PAGE_MASK) | __PAGE_KERNEL;
+         mcl[0].args[2] = 0;
+         mcl[0].args[3] = netif->domid;
+         mcl++;
+         memcpy(&pending_tx_info[pending_idx].req, &txreq, sizeof(txreq));
+         pending_tx_info[pending_idx].netif = netif;
+         *((u16 *)skb->data) = pending_idx;
+         __skb_queue_tail(&tx_queue, skb);
+         pending_cons++;
+         /* Filled the batch queue? */
+         if ( (mcl - tx_mcl) == ARRAY_SIZE(tx_mcl) )
+             break;
+     }
+     if ( mcl == tx_mcl )
+         return;
+     if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) )
+         BUG();
+     mcl = tx_mcl;
+     while ( (skb = __skb_dequeue(&tx_queue)) != NULL )
+     {
+         pending_idx = *((u16 *)skb->data);
+         netif       = pending_tx_info[pending_idx].netif;
+         memcpy(&txreq, &pending_tx_info[pending_idx].req, sizeof(txreq));
+         /* Check the remap error code. */
+         if ( unlikely(mcl[0].args[5] != 0) )
+         {
+             DPRINTK("Bad page frame\n");
+             make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
+             netif_put(netif);
+             kfree_skb(skb);
+             mcl++;
+             pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+             continue;
+         }
+         phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
+             FOREIGN_FRAME(txreq.addr >> PAGE_SHIFT);
+         data_len = txreq.size > PKT_PROT_LEN ? PKT_PROT_LEN : txreq.size;
+         __skb_put(skb, data_len);
+         memcpy(skb->data, 
+                (void *)(MMAP_VADDR(pending_idx)|(txreq.addr&~PAGE_MASK)),
+                data_len);
+         if (data_len < txreq.size) {
+             /* Append the packet payload as a fragment. */
+             skb_shinfo(skb)->frags[0].page        = 
+                 virt_to_page(MMAP_VADDR(pending_idx));
+             skb_shinfo(skb)->frags[0].size        = txreq.size - data_len;
+             skb_shinfo(skb)->frags[0].page_offset = 
+                 (txreq.addr + data_len) & ~PAGE_MASK;
+             skb_shinfo(skb)->nr_frags = 1;
+         } else {
+             skb_shinfo(skb)->frags[0].page        = 
+                 virt_to_page(MMAP_VADDR(pending_idx));
+             skb->destructor = netif_skb_release;
+         }
+         skb->data_len  = txreq.size - data_len;
+         skb->len      += skb->data_len;
+         skb->dev      = netif->dev;
+         skb->protocol = eth_type_trans(skb, skb->dev);
+         netif->stats.rx_bytes += txreq.size;
+         netif->stats.rx_packets++;
+         netif_rx(skb);
+         netif->dev->last_rx = jiffies;
+         mcl++;
+     }
+ }
+ static void netif_idx_release(u16 pending_idx)
+ {
+     unsigned long flags;
+     spin_lock_irqsave(&dealloc_lock, flags);
+     dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx;
+     spin_unlock_irqrestore(&dealloc_lock, flags);
+     tasklet_schedule(&net_tx_tasklet);
+ }
+ static void netif_page_release(struct page *page)
+ {
+     u16 pending_idx = page - virt_to_page(mmap_vstart);
+     /* Ready for next use. */
+     set_page_count(page, 1);
+     netif_idx_release(pending_idx);
+ }
+ static void netif_skb_release(struct sk_buff *skb)
+ {
+     struct page *page = skb_shinfo(skb)->frags[0].page;
+     u16 pending_idx = page - virt_to_page(mmap_vstart);
+     netif_idx_release(pending_idx);
+ }
+ #if 0
+ long flush_bufs_for_netif(netif_t *netif)
+ {
+     NETIF_RING_IDX i;
+     /* Return any outstanding receive buffers to the guest OS. */
+     spin_lock(&netif->rx_lock);
+     for ( i = netif->rx_req_cons; 
+           (i != netif->rx->req_prod) &&
+               ((i-netif->rx_resp_prod) != NETIF_RX_RING_SIZE);
+           i++ )
+     {
+         make_rx_response(netif,
+                          netif->rx->ring[MASK_NETIF_RX_IDX(i)].req.id,
+                          NETIF_RSP_DROPPED, 0, 0);
+     }
+     netif->rx_req_cons = i;
+     spin_unlock(&netif->rx_lock);
+     /*
+      * Flush pending transmit buffers. The guest may still have to wait for
+      * buffers that are queued at a physical NIC.
+      */
+     spin_lock(&netif->tx_lock);
+     for ( i = netif->tx_req_cons; 
+           (i != netif->tx->req_prod) &&
+               ((i-netif->tx_resp_prod) != NETIF_TX_RING_SIZE);
+           i++ )
+     {
+         make_tx_response(netif,
+                          netif->tx->ring[MASK_NETIF_TX_IDX(i)].req.id,
+                          NETIF_RSP_DROPPED);
+     }
+     netif->tx_req_cons = i;
+     spin_unlock(&netif->tx_lock);
+     return 0;
+ }
+ #endif
+ irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+ {
+     netif_t *netif = dev_id;
+     if ( tx_work_exists(netif) )
+     {
+         add_to_net_schedule_list_tail(netif);
+         maybe_schedule_tx_action();
+     }
+     return IRQ_HANDLED;
+ }
+ static void make_tx_response(netif_t *netif, 
+                              u16      id,
+                              s8       st)
+ {
+     NETIF_RING_IDX i = netif->tx_resp_prod;
+     netif_tx_response_t *resp;
+     resp = &netif->tx->ring[MASK_NETIF_TX_IDX(i)].resp;
+     resp->id     = id;
+     resp->status = st;
+     wmb();
+     netif->tx->resp_prod = netif->tx_resp_prod = ++i;
+     mb(); /* Update producer before checking event threshold. */
+     if ( i == netif->tx->event )
+         notify_via_evtchn(netif->evtchn);
+ }
+ static int make_rx_response(netif_t *netif, 
+                             u16      id, 
+                             s8       st,
+                             memory_t addr,
+                             u16      size)
+ {
+     NETIF_RING_IDX i = netif->rx_resp_prod;
+     netif_rx_response_t *resp;
+     resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
+     resp->addr   = addr;
+     resp->id     = id;
+     resp->status = (s16)size;
+     if ( st < 0 )
+         resp->status = (s16)st;
+     wmb();
+     netif->rx->resp_prod = netif->rx_resp_prod = ++i;
+     mb(); /* Update producer before checking event threshold. */
+     return (i == netif->rx->event);
+ }
+ static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
+ {
+     struct list_head *ent;
+     netif_t *netif;
+     int i = 0;
+     printk(KERN_ALERT "netif_schedule_list:\n");
+     spin_lock_irq(&net_schedule_list_lock);
+     list_for_each ( ent, &net_schedule_list )
+     {
+         netif = list_entry(ent, netif_t, list);
+         printk(KERN_ALERT " %d: private(rx_req_cons=%08x rx_resp_prod=%08x\n",
+                i, netif->rx_req_cons, netif->rx_resp_prod);               
+         printk(KERN_ALERT "   tx_req_cons=%08x tx_resp_prod=%08x)\n",
+                netif->tx_req_cons, netif->tx_resp_prod);
+         printk(KERN_ALERT "   shared(rx_req_prod=%08x rx_resp_prod=%08x\n",
+                netif->rx->req_prod, netif->rx->resp_prod);
+         printk(KERN_ALERT "   rx_event=%08x tx_req_prod=%08x\n",
+                netif->rx->event, netif->tx->req_prod);
+         printk(KERN_ALERT "   tx_resp_prod=%08x, tx_event=%08x)\n",
+                netif->tx->resp_prod, netif->tx->event);
+         i++;
+     }
+     spin_unlock_irq(&net_schedule_list_lock);
+     printk(KERN_ALERT " ** End of netif_schedule_list **\n");
+     return IRQ_HANDLED;
+ }
+ static int __init netback_init(void)
+ {
+     int i;
+     struct page *page;
+     if ( !(xen_start_info.flags & SIF_NET_BE_DOMAIN) &&
+        !(xen_start_info.flags & SIF_INITDOMAIN) )
+         return 0;
+     printk("Initialising Xen netif backend\n");
+     /* We can increase reservation by this much in net_rx_action(). */
+     balloon_update_driver_allowance(NETIF_RX_RING_SIZE);
+     skb_queue_head_init(&rx_queue);
+     skb_queue_head_init(&tx_queue);
+     init_timer(&net_timer);
+     net_timer.data = 0;
+     net_timer.function = net_alarm;
+     
+     netif_interface_init();
+     if ( (mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS)) == 0 )
+         BUG();
+     for ( i = 0; i < MAX_PENDING_REQS; i++ )
+     {
+         page = virt_to_page(MMAP_VADDR(i));
+         set_page_count(page, 1);
+         SetPageForeign(page, netif_page_release);
+     }
+     pending_cons = 0;
+     pending_prod = MAX_PENDING_REQS;
+     for ( i = 0; i < MAX_PENDING_REQS; i++ )
+         pending_ring[i] = i;
+     spin_lock_init(&net_schedule_list_lock);
+     INIT_LIST_HEAD(&net_schedule_list);
+     netif_ctrlif_init();
+     (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG),
+                       netif_be_dbg, SA_SHIRQ, 
+                       "net-be-dbg", &netif_be_dbg);
+     return 0;
+ }
+ static void netback_cleanup(void)
+ {
+     BUG();
+ }
+ module_init(netback_init);
+ module_exit(netback_cleanup);
index 0000000000000000000000000000000000000000,30f4d88b62dc47f80be9ea48e3f79d7fcf82d82b..dd28b4917527ae504268f99198a591ed42075501
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,131 +1,137 @@@
 -#define TIMER_IRQ             timer_irq
 -
+ /*
+  * This file should contain #defines for all of the interrupt vector
+  * numbers used by this architecture.
+  *
+  * In addition, there are some standard defines:
+  *
+  *    FIRST_EXTERNAL_VECTOR:
+  *            The first free place for external interrupts
+  *
+  *    SYSCALL_VECTOR:
+  *            The IRQ vector a syscall makes the user to kernel transition
+  *            under.
+  *
+  *    TIMER_IRQ:
+  *            The IRQ number the timer interrupt comes in at.
+  *
+  *    NR_IRQS:
+  *            The total number of interrupt vectors (including all the
+  *            architecture specific interrupts) needed.
+  *
+  */                   
+ #ifndef _ASM_IRQ_VECTORS_H
+ #define _ASM_IRQ_VECTORS_H
+ /*
+  * IDT vectors usable for external interrupt sources start
+  * at 0x20:
+  */
+ #define FIRST_EXTERNAL_VECTOR 0x20
+ #define SYSCALL_VECTOR                0x80
+ /*
+  * Vectors 0x20-0x2f are used for ISA interrupts.
+  */
++#if 0
+ /*
+  * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
+  *
+  *  some of the following vectors are 'rare', they are merged
+  *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
+  *  TLB, reschedule and local APIC vectors are performance-critical.
+  *
+  *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
+  */
+ #define SPURIOUS_APIC_VECTOR  0xff
+ #define ERROR_APIC_VECTOR     0xfe
+ #define INVALIDATE_TLB_VECTOR 0xfd
+ #define RESCHEDULE_VECTOR     0xfc
+ #define CALL_FUNCTION_VECTOR  0xfb
+ #define THERMAL_APIC_VECTOR   0xf0
+ /*
+  * Local APIC timer IRQ vector is on a different priority level,
+  * to work around the 'lost local interrupt if more than 2 IRQ
+  * sources per level' errata.
+  */
+ #define LOCAL_TIMER_VECTOR    0xef
++#endif
+ /*
+  * First APIC vector available to drivers: (vectors 0x30-0xee)
+  * we start at 0x31 to spread out vectors evenly between priority
+  * levels. (0x80 is the syscall vector)
+  */
+ #define FIRST_DEVICE_VECTOR   0x31
+ #define FIRST_SYSTEM_VECTOR   0xef
 -#if 0
+ /*
+  * 16 8259A IRQ's, 208 potential APIC interrupt sources.
+  * Right now the APIC is mostly only used for SMP.
+  * 256 vectors is an architectural limit. (we can have
+  * more than 256 devices theoretically, but they will
+  * have to use shared interrupts)
+  * Since vectors 0x00-0x1f are used/reserved for the CPU,
+  * the usable vector space is 0x20-0xff (224 vectors)
+  */
 -#endif
++#define NR_IPIS 8
++
++#define RESCHEDULE_VECTOR     1
++#define INVALIDATE_TLB_VECTOR 2
++#define CALL_FUNCTION_VECTOR  3
++
+ /*
+  * The maximum number of vectors supported by i386 processors
+  * is limited to 256. For processors other than i386, NR_VECTORS
+  * should be changed accordingly.
+  */
+ #define NR_VECTORS 256
 -#define NR_PIRQS              128
+ #define FPU_IRQ                       13
+ #define       FIRST_VM86_IRQ          3
+ #define LAST_VM86_IRQ         15
+ #define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15)
+ /*
+  * The flat IRQ space is divided into two regions:
+  *  1. A one-to-one mapping of real physical IRQs. This space is only used
+  *     if we have physical device-access privilege. This region is at the 
+  *     start of the IRQ space so that existing device drivers do not need
+  *     to be modified to translate physical IRQ numbers into our IRQ space.
+  *  3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
+  *     are bound using the provided bind/unbind functions.
+  */
+ #define PIRQ_BASE             0
 -#define NR_DYNIRQS            128
++#define NR_PIRQS              256
+ #define DYNIRQ_BASE           (PIRQ_BASE + NR_PIRQS)
++#define NR_DYNIRQS            256
+ #define NR_IRQS                       (NR_PIRQS + NR_DYNIRQS)
+ #define NR_IRQ_VECTORS                NR_IRQS
+ #define pirq_to_irq(_x)               ((_x) + PIRQ_BASE)
+ #define irq_to_pirq(_x)               ((_x) - PIRQ_BASE)
+ #define dynirq_to_irq(_x)     ((_x) + DYNIRQ_BASE)
+ #define irq_to_dynirq(_x)     ((_x) - DYNIRQ_BASE)
+ #ifndef __ASSEMBLY__
+ /* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
+ extern int  bind_virq_to_irq(int virq);
+ extern void unbind_virq_from_irq(int virq);
++extern int  bind_ipi_on_cpu_to_irq(int cpu, int ipi);
++extern void unbind_ipi_on_cpu_from_irq(int cpu, int ipi);
+ extern int  bind_evtchn_to_irq(int evtchn);
+ extern void unbind_evtchn_from_irq(int evtchn);
+ extern void irq_suspend(void);
+ extern void irq_resume(void);
+ #endif /* __ASSEMBLY__ */
+ #endif /* _ASM_IRQ_VECTORS_H */
index 0000000000000000000000000000000000000000,36a2420a2969e100ae9e31bd827118a2817061af..c7db3fee598885d4b031adee23c27ea4615e0c1c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,136 +1,148 @@@
+ #ifndef _I386_PGTABLE_2LEVEL_H
+ #define _I386_PGTABLE_2LEVEL_H
+ #define pte_ERROR(e) \
+       printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
+ #define pmd_ERROR(e) \
+       printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+ #define pgd_ERROR(e) \
+       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+ /*
+  * The "pgd_xxx()" functions here are trivial for a folded two-level
+  * setup: the pgd is never bad, and a pmd always exists (as it's folded
+  * into the pgd entry)
+  */
+ static inline int pgd_none(pgd_t pgd)         { return 0; }
+ static inline int pgd_bad(pgd_t pgd)          { return 0; }
+ static inline int pgd_present(pgd_t pgd)      { return 1; }
+ #define pgd_clear(xp)                         do { } while (0)
+ /*
+  * Certain architectures need to do special things when PTEs
+  * within a page table are directly modified.  Thus, the following
+  * hook is made available.
+  */
+ #define set_pte_batched(pteptr, pteval) \
+       queue_l1_entry_update(pteptr, (pteval).pte_low)
++
++#ifdef CONFIG_SMP
++#define set_pte(pteptr, pteval) xen_l1_entry_update(pteptr, (pteval).pte_low)
++#if 0
++do { \
++  (*(pteptr) = pteval); \
++  HYPERVISOR_xen_version(0); \
++} while (0)
++#endif
++#define set_pte_atomic(pteptr, pteval) set_pte(pteptr, pteval)
++#else
+ #define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+ #define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
++#endif
+ /*
+  * (pmds are folded into pgds so this doesn't get actually called,
+  * but the define is needed for a generic inline function.)
+  */
+ #define set_pmd(pmdptr, pmdval) xen_l2_entry_update((pmdptr), (pmdval).pmd)
+ #define set_pgd(pgdptr, pgdval) ((void)0)
+ #define pgd_page(pgd) \
+ ((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
+ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+ {
+       return (pmd_t *) dir;
+ }
+ /*
+  * A note on implementation of this atomic 'get-and-clear' operation.
+  * This is actually very simple because Xen Linux can only run on a single
+  * processor. Therefore, we cannot race other processors setting the 'accessed'
+  * or 'dirty' bits on a page-table entry.
+  * Even if pages are shared between domains, that is not a problem because
+  * each domain will have separate page tables, with their own versions of
+  * accessed & dirty state.
+  */
+ static inline pte_t ptep_get_and_clear(pte_t *xp)
+ {
+       pte_t pte = *xp;
+       if (pte.pte_low)
+               set_pte(xp, __pte_ma(0));
+       return pte;
+ }
+ #define pte_same(a, b)                ((a).pte_low == (b).pte_low)
+ /*
+  * We detect special mappings in one of two ways:
+  *  1. If the MFN is an I/O page then Xen will set the m2p entry
+  *     to be outside our maximum possible pseudophys range.
+  *  2. If the MFN belongs to a different domain then we will certainly
+  *     not have MFN in our p2m table. Conversely, if the page is ours,
+  *     then we'll have p2m(m2p(MFN))==MFN.
+  * If we detect a special mapping then it doesn't have a 'struct page'.
+  * We force !pfn_valid() by returning an out-of-range pointer.
+  *
+  * NB. These checks require that, for any MFN that is not in our reservation,
+  * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+  * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+  * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+  * 
+  * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+  *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+  *      require. In all the cases we care about, the high bit gets shifted out
+  *      (e.g., phys_to_machine()) so behaviour there is correct.
+  */
+ #define INVALID_P2M_ENTRY (~0UL)
+ #define FOREIGN_FRAME(_m) ((_m) | (1UL<<((sizeof(unsigned long)*8)-1)))
+ #define pte_pfn(_pte)                                                 \
+ ({                                                                    \
+       unsigned long mfn = (_pte).pte_low >> PAGE_SHIFT;               \
+       unsigned long pfn = mfn_to_pfn(mfn);                            \
+       if ((pfn >= max_mapnr) || (pfn_to_mfn(pfn) != mfn))             \
+               pfn = max_mapnr; /* special: force !pfn_valid() */      \
+       pfn;                                                            \
+ })
+ #define pte_page(_pte) pfn_to_page(pte_pfn(_pte))
+ #define pte_none(x)           (!(x).pte_low)
+ #define pfn_pte(pfn, prot)    __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+ #define pfn_pte_ma(pfn, prot) __pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+ #define pfn_pmd(pfn, prot)    __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+ /*
+  * All present user pages are user-executable:
+  */
+ static inline int pte_exec(pte_t pte)
+ {
+       return pte_user(pte);
+ }
+ /*
+  * All present pages are kernel-executable:
+  */
+ static inline int pte_exec_kernel(pte_t pte)
+ {
+       return 1;
+ }
+ /*
+  * Bits 0, 6 and 7 are taken, split up the 29 bits of offset
+  * into this range:
+  */
+ #define PTE_FILE_MAX_BITS     29
+ #define pte_to_pgoff(pte) \
+       ((((pte).pte_low >> 1) & 0x1f ) + (((pte).pte_low >> 8) << 5 ))
+ #define pgoff_to_pte(off) \
+       ((pte_t) { (((off) & 0x1f) << 1) + (((off) >> 5) << 8) + _PAGE_FILE })
+ /* Encode and de-code a swap entry */
+ #define __swp_type(x)                 (((x).val >> 1) & 0x1f)
+ #define __swp_offset(x)                       ((x).val >> 8)
+ #define __swp_entry(type, offset)     ((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+ #define __pte_to_swp_entry(pte)               ((swp_entry_t) { (pte).pte_low })
+ #define __swp_entry_to_pte(x)         ((pte_t) { (x).val })
+ #endif /* _I386_PGTABLE_2LEVEL_H */
index 0000000000000000000000000000000000000000,53b71d3113b5ce006a6ea723b42a840476f4e1e7..2e89e92e040d9ad35e2696eac265c9142e8c61da
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,676 +1,676 @@@
 -extern pgd_t *cur_pgd;                /* XXXsmp */
+ /*
+  * include/asm-i386/processor.h
+  *
+  * Copyright (C) 1994 Linus Torvalds
+  */
+ #ifndef __ASM_I386_PROCESSOR_H
+ #define __ASM_I386_PROCESSOR_H
+ #include <asm/vm86.h>
+ #include <asm/math_emu.h>
+ #include <asm/segment.h>
+ #include <asm/page.h>
+ #include <asm/types.h>
+ #include <asm/sigcontext.h>
+ #include <asm/cpufeature.h>
+ #include <asm/msr.h>
+ #include <asm/system.h>
+ #include <linux/cache.h>
+ #include <linux/config.h>
+ #include <linux/threads.h>
+ #include <asm/percpu.h>
+ /* flag for disabling the tsc */
+ extern int tsc_disable;
+ struct desc_struct {
+       unsigned long a,b;
+ };
+ #define desc_empty(desc) \
+               (!((desc)->a + (desc)->b))
+ #define desc_equal(desc1, desc2) \
+               (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
+ /*
+  * Default implementation of macro that returns current
+  * instruction pointer ("program counter").
+  */
+ #define current_text_addr() ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
+ /*
+  *  CPU type and hardware bug flags. Kept separately for each CPU.
+  *  Members of this structure are referenced in head.S, so think twice
+  *  before touching them. [mj]
+  */
+ struct cpuinfo_x86 {
+       __u8    x86;            /* CPU family */
+       __u8    x86_vendor;     /* CPU vendor */
+       __u8    x86_model;
+       __u8    x86_mask;
+       char    wp_works_ok;    /* It doesn't on 386's */
+       char    hlt_works_ok;   /* Problems on some 486Dx4's and old 386's */
+       char    hard_math;
+       char    rfu;
+               int     cpuid_level;    /* Maximum supported CPUID level, -1=no CPUID */
+       unsigned long   x86_capability[NCAPINTS];
+       char    x86_vendor_id[16];
+       char    x86_model_id[64];
+       int     x86_cache_size;  /* in KB - valid for CPUS which support this
+                                   call  */
+       int     x86_cache_alignment;    /* In bytes */
+       int     fdiv_bug;
+       int     f00f_bug;
+       int     coma_bug;
+       unsigned long loops_per_jiffy;
+ } __attribute__((__aligned__(SMP_CACHE_BYTES)));
+ #define X86_VENDOR_INTEL 0
+ #define X86_VENDOR_CYRIX 1
+ #define X86_VENDOR_AMD 2
+ #define X86_VENDOR_UMC 3
+ #define X86_VENDOR_NEXGEN 4
+ #define X86_VENDOR_CENTAUR 5
+ #define X86_VENDOR_RISE 6
+ #define X86_VENDOR_TRANSMETA 7
+ #define X86_VENDOR_NSC 8
+ #define X86_VENDOR_NUM 9
+ #define X86_VENDOR_UNKNOWN 0xff
+ /*
+  * capabilities of CPUs
+  */
+ extern struct cpuinfo_x86 boot_cpu_data;
+ extern struct cpuinfo_x86 new_cpu_data;
+ extern struct tss_struct doublefault_tss;
+ DECLARE_PER_CPU(struct tss_struct, init_tss);
 -      cur_pgd = pgdir;        /* XXXsmp */            \
++DECLARE_PER_CPU(pgd_t *, cur_pgd);
+ #ifdef CONFIG_SMP
+ extern struct cpuinfo_x86 cpu_data[];
+ #define current_cpu_data cpu_data[smp_processor_id()]
+ #else
+ #define cpu_data (&boot_cpu_data)
+ #define current_cpu_data boot_cpu_data
+ #endif
+ extern char ignore_fpu_irq;
+ extern void identify_cpu(struct cpuinfo_x86 *);
+ extern void print_cpu_info(struct cpuinfo_x86 *);
+ extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+ extern void dodgy_tsc(void);
+ /*
+  * EFLAGS bits
+  */
+ #define X86_EFLAGS_CF 0x00000001 /* Carry Flag */
+ #define X86_EFLAGS_PF 0x00000004 /* Parity Flag */
+ #define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */
+ #define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */
+ #define X86_EFLAGS_SF 0x00000080 /* Sign Flag */
+ #define X86_EFLAGS_TF 0x00000100 /* Trap Flag */
+ #define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */
+ #define X86_EFLAGS_DF 0x00000400 /* Direction Flag */
+ #define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */
+ #define X86_EFLAGS_IOPL       0x00003000 /* IOPL mask */
+ #define X86_EFLAGS_NT 0x00004000 /* Nested Task */
+ #define X86_EFLAGS_RF 0x00010000 /* Resume Flag */
+ #define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */
+ #define X86_EFLAGS_AC 0x00040000 /* Alignment Check */
+ #define X86_EFLAGS_VIF        0x00080000 /* Virtual Interrupt Flag */
+ #define X86_EFLAGS_VIP        0x00100000 /* Virtual Interrupt Pending */
+ #define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */
+ /*
+  * Generic CPUID function
+  */
+ static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
+ {
+       __asm__("cpuid"
+               : "=a" (*eax),
+                 "=b" (*ebx),
+                 "=c" (*ecx),
+                 "=d" (*edx)
+               : "0" (op));
+ }
+ /*
+  * CPUID functions returning a single datum
+  */
+ static inline unsigned int cpuid_eax(unsigned int op)
+ {
+       unsigned int eax;
+       __asm__("cpuid"
+               : "=a" (eax)
+               : "0" (op)
+               : "bx", "cx", "dx");
+       return eax;
+ }
+ static inline unsigned int cpuid_ebx(unsigned int op)
+ {
+       unsigned int eax, ebx;
+       __asm__("cpuid"
+               : "=a" (eax), "=b" (ebx)
+               : "0" (op)
+               : "cx", "dx" );
+       return ebx;
+ }
+ static inline unsigned int cpuid_ecx(unsigned int op)
+ {
+       unsigned int eax, ecx;
+       __asm__("cpuid"
+               : "=a" (eax), "=c" (ecx)
+               : "0" (op)
+               : "bx", "dx" );
+       return ecx;
+ }
+ static inline unsigned int cpuid_edx(unsigned int op)
+ {
+       unsigned int eax, edx;
+       __asm__("cpuid"
+               : "=a" (eax), "=d" (edx)
+               : "0" (op)
+               : "bx", "cx");
+       return edx;
+ }
+ #define load_cr3(pgdir) do {                          \
+       queue_pt_switch(__pa(pgdir));                   \
++      per_cpu(cur_pgd, smp_processor_id()) = pgdir;   \
+ } while (/* CONSTCOND */0)
+ /*
+  * Intel CPU features in CR4
+  */
+ #define X86_CR4_VME           0x0001  /* enable vm86 extensions */
+ #define X86_CR4_PVI           0x0002  /* virtual interrupts flag enable */
+ #define X86_CR4_TSD           0x0004  /* disable time stamp at ipl 3 */
+ #define X86_CR4_DE            0x0008  /* enable debugging extensions */
+ #define X86_CR4_PSE           0x0010  /* enable page size extensions */
+ #define X86_CR4_PAE           0x0020  /* enable physical address extensions */
+ #define X86_CR4_MCE           0x0040  /* Machine check enable */
+ #define X86_CR4_PGE           0x0080  /* enable global pages */
+ #define X86_CR4_PCE           0x0100  /* enable performance counters at ipl 3 */
+ #define X86_CR4_OSFXSR                0x0200  /* enable fast FPU save and restore */
+ #define X86_CR4_OSXMMEXCPT    0x0400  /* enable unmasked SSE exceptions */
+ /*
+  * Save the cr4 feature set we're using (ie
+  * Pentium 4MB enable and PPro Global page
+  * enable), so that any CPU's that boot up
+  * after us can get the correct flags.
+  */
+ extern unsigned long mmu_cr4_features;
+ static inline void set_in_cr4 (unsigned long mask)
+ {
+       mmu_cr4_features |= mask;
+       switch (mask) {
+       case X86_CR4_OSFXSR:
+       case X86_CR4_OSXMMEXCPT:
+               break;
+       default:
+               do {
+                       const char *msg = "Xen unsupported cr4 update\n";
+                       (void)HYPERVISOR_console_io(
+                               CONSOLEIO_write, __builtin_strlen(msg),
+                               (char *)msg);
+                       BUG();
+               } while (0);
+       }
+ }
+ static inline void clear_in_cr4 (unsigned long mask)
+ {
+       mmu_cr4_features &= ~mask;
+       __asm__("movl %%cr4,%%eax\n\t"
+               "andl %0,%%eax\n\t"
+               "movl %%eax,%%cr4\n"
+               : : "irg" (~mask)
+               :"ax");
+ }
+ /*
+  *      NSC/Cyrix CPU configuration register indexes
+  */
+ #define CX86_PCR0 0x20
+ #define CX86_GCR  0xb8
+ #define CX86_CCR0 0xc0
+ #define CX86_CCR1 0xc1
+ #define CX86_CCR2 0xc2
+ #define CX86_CCR3 0xc3
+ #define CX86_CCR4 0xe8
+ #define CX86_CCR5 0xe9
+ #define CX86_CCR6 0xea
+ #define CX86_CCR7 0xeb
+ #define CX86_PCR1 0xf0
+ #define CX86_DIR0 0xfe
+ #define CX86_DIR1 0xff
+ #define CX86_ARR_BASE 0xc4
+ #define CX86_RCR_BASE 0xdc
+ /*
+  *      NSC/Cyrix CPU indexed register access macros
+  */
+ #define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
+ #define setCx86(reg, data) do { \
+       outb((reg), 0x22); \
+       outb((data), 0x23); \
+ } while (0)
+ /*
+  * Bus types (default is ISA, but people can check others with these..)
+  */
+ extern int MCA_bus;
+ static inline void __monitor(const void *eax, unsigned long ecx,
+               unsigned long edx)
+ {
+       /* "monitor %eax,%ecx,%edx;" */
+       asm volatile(
+               ".byte 0x0f,0x01,0xc8;"
+               : :"a" (eax), "c" (ecx), "d"(edx));
+ }
+ static inline void __mwait(unsigned long eax, unsigned long ecx)
+ {
+       /* "mwait %eax,%ecx;" */
+       asm volatile(
+               ".byte 0x0f,0x01,0xc9;"
+               : :"a" (eax), "c" (ecx));
+ }
+ /* from system description table in BIOS.  Mostly for MCA use, but
+ others may find it useful. */
+ extern unsigned int machine_id;
+ extern unsigned int machine_submodel_id;
+ extern unsigned int BIOS_revision;
+ extern unsigned int mca_pentium_flag;
+ /*
+  * User space process size: 3GB (default).
+  */
+ #define TASK_SIZE     (PAGE_OFFSET)
+ /* This decides where the kernel will search for a free chunk of vm
+  * space during mmap's.
+  */
+ #define TASK_UNMAPPED_BASE    (PAGE_ALIGN(TASK_SIZE / 3))
+ #define HAVE_ARCH_PICK_MMAP_LAYOUT
+ /*
+  * Size of io_bitmap.
+  */
+ #define IO_BITMAP_BITS  65536
+ #define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
+ #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
+ #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
+ #define INVALID_IO_BITMAP_OFFSET 0x8000
+ #define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
+ struct i387_fsave_struct {
+       long    cwd;
+       long    swd;
+       long    twd;
+       long    fip;
+       long    fcs;
+       long    foo;
+       long    fos;
+       long    st_space[20];   /* 8*10 bytes for each FP-reg = 80 bytes */
+       long    status;         /* software status information */
+ };
+ struct i387_fxsave_struct {
+       unsigned short  cwd;
+       unsigned short  swd;
+       unsigned short  twd;
+       unsigned short  fop;
+       long    fip;
+       long    fcs;
+       long    foo;
+       long    fos;
+       long    mxcsr;
+       long    mxcsr_mask;
+       long    st_space[32];   /* 8*16 bytes for each FP-reg = 128 bytes */
+       long    xmm_space[32];  /* 8*16 bytes for each XMM-reg = 128 bytes */
+       long    padding[56];
+ } __attribute__ ((aligned (16)));
+ struct i387_soft_struct {
+       long    cwd;
+       long    swd;
+       long    twd;
+       long    fip;
+       long    fcs;
+       long    foo;
+       long    fos;
+       long    st_space[20];   /* 8*10 bytes for each FP-reg = 80 bytes */
+       unsigned char   ftop, changed, lookahead, no_update, rm, alimit;
+       struct info     *info;
+       unsigned long   entry_eip;
+ };
+ union i387_union {
+       struct i387_fsave_struct        fsave;
+       struct i387_fxsave_struct       fxsave;
+       struct i387_soft_struct soft;
+ };
+ typedef struct {
+       unsigned long seg;
+ } mm_segment_t;
+ struct thread_struct;
+ struct tss_struct {
+       unsigned short  back_link,__blh;
+       unsigned long   esp0;
+       unsigned short  ss0,__ss0h;
+       unsigned long   esp1;
+       unsigned short  ss1,__ss1h;     /* ss1 is used to cache MSR_IA32_SYSENTER_CS */
+       unsigned long   esp2;
+       unsigned short  ss2,__ss2h;
+       unsigned long   __cr3;
+       unsigned long   eip;
+       unsigned long   eflags;
+       unsigned long   eax,ecx,edx,ebx;
+       unsigned long   esp;
+       unsigned long   ebp;
+       unsigned long   esi;
+       unsigned long   edi;
+       unsigned short  es, __esh;
+       unsigned short  cs, __csh;
+       unsigned short  ss, __ssh;
+       unsigned short  ds, __dsh;
+       unsigned short  fs, __fsh;
+       unsigned short  gs, __gsh;
+       unsigned short  ldt, __ldth;
+       unsigned short  trace, io_bitmap_base;
+       /*
+        * The extra 1 is there because the CPU will access an
+        * additional byte beyond the end of the IO permission
+        * bitmap. The extra byte must be all 1 bits, and must
+        * be within the limit.
+        */
+       unsigned long   io_bitmap[IO_BITMAP_LONGS + 1];
+       /*
+        * Cache the current maximum and the last task that used the bitmap:
+        */
+       unsigned long io_bitmap_max;
+       struct thread_struct *io_bitmap_owner;
+       /*
+        * pads the TSS to be cacheline-aligned (size is 0x100)
+        */
+       unsigned long __cacheline_filler[35];
+       /*
+        * .. and then another 0x100 bytes for emergency kernel stack
+        */
+       unsigned long stack[64];
+ } __attribute__((packed));
+ #define ARCH_MIN_TASKALIGN    16
+ struct thread_struct {
+ /* cached TLS descriptors. */
+       struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
+       unsigned long   esp0;
+       unsigned long   sysenter_cs;
+       unsigned long   eip;
+       unsigned long   esp;
+       unsigned long   fs;
+       unsigned long   gs;
+       unsigned int    io_pl;
+ /* Hardware debugging registers */
+       unsigned long   debugreg[8];  /* %%db0-7 debug registers */
+ /* fault info */
+       unsigned long   cr2, trap_no, error_code;
+ /* floating point info */
+       union i387_union        i387;
+ /* virtual 86 mode info */
+       struct vm86_struct __user * vm86_info;
+       unsigned long           screen_bitmap;
+       unsigned long           v86flags, v86mask, saved_esp0;
+       unsigned int            saved_fs, saved_gs;
+ /* IO permissions */
+       unsigned long   *io_bitmap_ptr;
+ /* max allowed port in the bitmap, in bytes: */
+       unsigned long   io_bitmap_max;
+ };
+ #define INIT_THREAD  {                                                        \
+       .vm86_info = NULL,                                              \
+       .sysenter_cs = __KERNEL_CS,                                     \
+       .io_bitmap_ptr = NULL,                                          \
+ }
+ /*
+  * Note that the .io_bitmap member must be extra-big. This is because
+  * the CPU will access an additional byte beyond the end of the IO
+  * permission bitmap. The extra byte must be all 1 bits, and must
+  * be within the limit.
+  */
+ #define INIT_TSS  {                                                   \
+       .esp0           = sizeof(init_stack) + (long)&init_stack,       \
+       .ss0            = __KERNEL_DS,                                  \
+       .ss1            = __KERNEL_CS,                                  \
+       .ldt            = GDT_ENTRY_LDT,                                \
+       .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,                     \
+       .io_bitmap      = { [ 0 ... IO_BITMAP_LONGS] = ~0 },            \
+ }
+ static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread)
+ {
+       tss->esp0 = thread->esp0;
+       /* This can only happen when SEP is enabled, no need to test "SEP"arately */
+       if (unlikely(tss->ss1 != thread->sysenter_cs)) {
+               tss->ss1 = thread->sysenter_cs;
+               wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+       }
+       HYPERVISOR_stack_switch(tss->ss0, tss->esp0);
+ }
+ #define start_thread(regs, new_eip, new_esp) do {             \
+       __asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0));       \
+       set_fs(USER_DS);                                        \
+       regs->xds = __USER_DS;                                  \
+       regs->xes = __USER_DS;                                  \
+       regs->xss = __USER_DS;                                  \
+       regs->xcs = __USER_CS;                                  \
+       regs->eip = new_eip;                                    \
+       regs->esp = new_esp;                                    \
+ } while (0)
+ /* Forward declaration, a strange C thing */
+ struct task_struct;
+ struct mm_struct;
+ /* Free all resources held by a thread. */
+ extern void release_thread(struct task_struct *);
+ /* Prepare to copy thread state - unlazy all lazy status */
+ extern void prepare_to_copy(struct task_struct *tsk);
+ /*
+  * create a kernel thread without removing it from tasklists
+  */
+ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+ void show_trace(struct task_struct *task, unsigned long *stack);
+ unsigned long get_wchan(struct task_struct *p);
+ #define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
+ #define KSTK_TOP(info)                                                 \
+ ({                                                                     \
+        unsigned long *__ptr = (unsigned long *)(info);                 \
+        (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
+ })
+ #define task_pt_regs(task)                                             \
+ ({                                                                     \
+        struct pt_regs *__regs__;                                       \
+        __regs__ = (struct pt_regs *)KSTK_TOP((task)->thread_info);     \
+        __regs__ - 1;                                                   \
+ })
+ #define KSTK_EIP(task) (task_pt_regs(task)->eip)
+ #define KSTK_ESP(task) (task_pt_regs(task)->esp)
+ struct microcode_header {
+       unsigned int hdrver;
+       unsigned int rev;
+       unsigned int date;
+       unsigned int sig;
+       unsigned int cksum;
+       unsigned int ldrver;
+       unsigned int pf;
+       unsigned int datasize;
+       unsigned int totalsize;
+       unsigned int reserved[3];
+ };
+ struct microcode {
+       struct microcode_header hdr;
+       unsigned int bits[0];
+ };
+ typedef struct microcode microcode_t;
+ typedef struct microcode_header microcode_header_t;
+ /* microcode format is extended from prescott processors */
+ struct extended_signature {
+       unsigned int sig;
+       unsigned int pf;
+       unsigned int cksum;
+ };
+ struct extended_sigtable {
+       unsigned int count;
+       unsigned int cksum;
+       unsigned int reserved[3];
+       struct extended_signature sigs[0];
+ };
+ /* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */
+ #define MICROCODE_IOCFREE     _IO('6',0)
+ /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+ static inline void rep_nop(void)
+ {
+       __asm__ __volatile__("rep;nop": : :"memory");
+ }
+ #define cpu_relax()   rep_nop()
+ /* generic versions from gas */
+ #define GENERIC_NOP1  ".byte 0x90\n"
+ #define GENERIC_NOP2          ".byte 0x89,0xf6\n"
+ #define GENERIC_NOP3        ".byte 0x8d,0x76,0x00\n"
+ #define GENERIC_NOP4        ".byte 0x8d,0x74,0x26,0x00\n"
+ #define GENERIC_NOP5        GENERIC_NOP1 GENERIC_NOP4
+ #define GENERIC_NOP6  ".byte 0x8d,0xb6,0x00,0x00,0x00,0x00\n"
+ #define GENERIC_NOP7  ".byte 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00\n"
+ #define GENERIC_NOP8  GENERIC_NOP1 GENERIC_NOP7
+ /* Opteron nops */
+ #define K8_NOP1 GENERIC_NOP1
+ #define K8_NOP2       ".byte 0x66,0x90\n" 
+ #define K8_NOP3       ".byte 0x66,0x66,0x90\n" 
+ #define K8_NOP4       ".byte 0x66,0x66,0x66,0x90\n" 
+ #define K8_NOP5       K8_NOP3 K8_NOP2 
+ #define K8_NOP6       K8_NOP3 K8_NOP3
+ #define K8_NOP7       K8_NOP4 K8_NOP3
+ #define K8_NOP8       K8_NOP4 K8_NOP4
+ /* K7 nops */
+ /* uses eax dependencies (arbitary choice) */
+ #define K7_NOP1  GENERIC_NOP1
+ #define K7_NOP2       ".byte 0x8b,0xc0\n" 
+ #define K7_NOP3       ".byte 0x8d,0x04,0x20\n"
+ #define K7_NOP4       ".byte 0x8d,0x44,0x20,0x00\n"
+ #define K7_NOP5       K7_NOP4 ASM_NOP1
+ #define K7_NOP6       ".byte 0x8d,0x80,0,0,0,0\n"
+ #define K7_NOP7        ".byte 0x8D,0x04,0x05,0,0,0,0\n"
+ #define K7_NOP8        K7_NOP7 ASM_NOP1
+ #ifdef CONFIG_MK8
+ #define ASM_NOP1 K8_NOP1
+ #define ASM_NOP2 K8_NOP2
+ #define ASM_NOP3 K8_NOP3
+ #define ASM_NOP4 K8_NOP4
+ #define ASM_NOP5 K8_NOP5
+ #define ASM_NOP6 K8_NOP6
+ #define ASM_NOP7 K8_NOP7
+ #define ASM_NOP8 K8_NOP8
+ #elif defined(CONFIG_MK7)
+ #define ASM_NOP1 K7_NOP1
+ #define ASM_NOP2 K7_NOP2
+ #define ASM_NOP3 K7_NOP3
+ #define ASM_NOP4 K7_NOP4
+ #define ASM_NOP5 K7_NOP5
+ #define ASM_NOP6 K7_NOP6
+ #define ASM_NOP7 K7_NOP7
+ #define ASM_NOP8 K7_NOP8
+ #else
+ #define ASM_NOP1 GENERIC_NOP1
+ #define ASM_NOP2 GENERIC_NOP2
+ #define ASM_NOP3 GENERIC_NOP3
+ #define ASM_NOP4 GENERIC_NOP4
+ #define ASM_NOP5 GENERIC_NOP5
+ #define ASM_NOP6 GENERIC_NOP6
+ #define ASM_NOP7 GENERIC_NOP7
+ #define ASM_NOP8 GENERIC_NOP8
+ #endif
+ #define ASM_NOP_MAX 8
+ /* Prefetch instructions for Pentium III and AMD Athlon */
+ /* It's not worth to care about 3dnow! prefetches for the K6
+    because they are microcoded there and very slow.
+    However we don't do prefetches for pre XP Athlons currently
+    That should be fixed. */
+ #define ARCH_HAS_PREFETCH
+ extern inline void prefetch(const void *x)
+ {
+       alternative_input(ASM_NOP4,
+                         "prefetchnta (%1)",
+                         X86_FEATURE_XMM,
+                         "r" (x));
+ }
+ #define ARCH_HAS_PREFETCH
+ #define ARCH_HAS_PREFETCHW
+ #define ARCH_HAS_SPINLOCK_PREFETCH
+ /* 3dnow! prefetch to get an exclusive cache line. Useful for 
+    spinlocks to avoid one state transition in the cache coherency protocol. */
+ extern inline void prefetchw(const void *x)
+ {
+       alternative_input(ASM_NOP4,
+                         "prefetchw (%1)",
+                         X86_FEATURE_3DNOW,
+                         "r" (x));
+ }
+ #define spin_lock_prefetch(x) prefetchw(x)
+ extern void select_idle_routine(const struct cpuinfo_x86 *c);
+ #define cache_line_size() (boot_cpu_data.x86_cache_alignment)
+ extern unsigned long boot_option_idle_override;
+ #endif /* __ASM_I386_PROCESSOR_H */
index 0000000000000000000000000000000000000000,b8eb62d37a4ea6c91e412ccedc7eb43da64f4fd6..78f760df032ffdbd4677597ae9df5868b0dff7f1
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,521 +1,527 @@@
 -#include <asm-xen/evtchn.h>
+ #ifndef __ASM_SYSTEM_H
+ #define __ASM_SYSTEM_H
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/bitops.h>
+ #include <asm/synch_bitops.h>
+ #include <asm/segment.h>
+ #include <asm/cpufeature.h>
+ #include <asm-xen/hypervisor.h>
 - * critical operations are executed. All critical operatiosn must complete
+ #ifdef __KERNEL__
+ struct task_struct;   /* one of the stranger aspects of C forward declarations.. */
+ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
+ #define switch_to(prev,next,last) do {                                        \
+       unsigned long esi,edi;                                          \
+       asm volatile("pushfl\n\t"                                       \
+                    "pushl %%ebp\n\t"                                  \
+                    "movl %%esp,%0\n\t"        /* save ESP */          \
+                    "movl %5,%%esp\n\t"        /* restore ESP */       \
+                    "movl $1f,%1\n\t"          /* save EIP */          \
+                    "pushl %6\n\t"             /* restore EIP */       \
+                    "jmp __switch_to\n"                                \
+                    "1:\t"                                             \
+                    "popl %%ebp\n\t"                                   \
+                    "popfl"                                            \
+                    :"=m" (prev->thread.esp),"=m" (prev->thread.eip),  \
+                     "=a" (last),"=S" (esi),"=D" (edi)                 \
+                    :"m" (next->thread.esp),"m" (next->thread.eip),    \
+                     "2" (prev), "d" (next));                          \
+ } while (0)
+ #define _set_base(addr,base) do { unsigned long __pr; \
+ __asm__ __volatile__ ("movw %%dx,%1\n\t" \
+       "rorl $16,%%edx\n\t" \
+       "movb %%dl,%2\n\t" \
+       "movb %%dh,%3" \
+       :"=&d" (__pr) \
+       :"m" (*((addr)+2)), \
+        "m" (*((addr)+4)), \
+        "m" (*((addr)+7)), \
+          "0" (base) \
+         ); } while(0)
+ #define _set_limit(addr,limit) do { unsigned long __lr; \
+ __asm__ __volatile__ ("movw %%dx,%1\n\t" \
+       "rorl $16,%%edx\n\t" \
+       "movb %2,%%dh\n\t" \
+       "andb $0xf0,%%dh\n\t" \
+       "orb %%dh,%%dl\n\t" \
+       "movb %%dl,%2" \
+       :"=&d" (__lr) \
+       :"m" (*(addr)), \
+        "m" (*((addr)+6)), \
+        "0" (limit) \
+         ); } while(0)
+ #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) )
+ #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1)>>12 )
+ static inline unsigned long _get_base(char * addr)
+ {
+       unsigned long __base;
+       __asm__("movb %3,%%dh\n\t"
+               "movb %2,%%dl\n\t"
+               "shll $16,%%edx\n\t"
+               "movw %1,%%dx"
+               :"=&d" (__base)
+               :"m" (*((addr)+2)),
+                "m" (*((addr)+4)),
+                "m" (*((addr)+7)));
+       return __base;
+ }
+ #define get_base(ldt) _get_base( ((char *)&(ldt)) )
+ /*
+  * Load a segment. Fall back on loading the zero
+  * segment if something goes wrong..
+  */
+ #define loadsegment(seg,value)                        \
+       asm volatile("\n"                       \
+               "1:\t"                          \
+               "movl %0,%%" #seg "\n"          \
+               "2:\n"                          \
+               ".section .fixup,\"ax\"\n"      \
+               "3:\t"                          \
+               "pushl $0\n\t"                  \
+               "popl %%" #seg "\n\t"           \
+               "jmp 2b\n"                      \
+               ".previous\n"                   \
+               ".section __ex_table,\"a\"\n\t" \
+               ".align 4\n\t"                  \
+               ".long 1b,3b\n"                 \
+               ".previous"                     \
+               : :"m" (*(unsigned int *)&(value)))
+ /*
+  * Save a segment register away
+  */
+ #define savesegment(seg, value) \
+       asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
+ /*
+  * Clear and set 'TS' bit respectively
+  */
+ /* NB. 'clts' is done for us by Xen during virtual trap. */
+ #define clts() ((void)0)
+ #define read_cr0() \
+       BUG();
+ #define write_cr0(x) \
+       BUG();
+ #define read_cr4() \
+       BUG();
+ #define write_cr4(x) \
+       BUG();
+ #define stts() (HYPERVISOR_fpu_taskswitch())
+ #endif        /* __KERNEL__ */
+ static inline void wbinvd(void)
+ {
+       mmu_update_t u;
+       u.ptr = MMU_EXTENDED_COMMAND;
+       u.val = MMUEXT_FLUSH_CACHE;
+       (void)HYPERVISOR_mmu_update(&u, 1, NULL);
+ }
+ static inline unsigned long get_limit(unsigned long segment)
+ {
+       unsigned long __limit;
+       __asm__("lsll %1,%0"
+               :"=r" (__limit):"r" (segment));
+       return __limit+1;
+ }
+ #define nop() __asm__ __volatile__ ("nop")
+ #define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+ #define tas(ptr) (xchg((ptr),1))
+ struct __xchg_dummy { unsigned long a[100]; };
+ #define __xg(x) ((struct __xchg_dummy *)(x))
+ /*
+  * The semantics of XCHGCMP8B are a bit strange, this is why
+  * there is a loop and the loading of %%eax and %%edx has to
+  * be inside. This inlines well in most cases, the cached
+  * cost is around ~38 cycles. (in the future we might want
+  * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that
+  * might have an implicit FPU-save as a cost, so it's not
+  * clear which path to go.)
+  *
+  * cmpxchg8b must be used with the lock prefix here to allow
+  * the instruction to be executed atomically, see page 3-102
+  * of the instruction set reference 24319102.pdf. We need
+  * the reader side to see the coherent 64bit value.
+  */
+ static inline void __set_64bit (unsigned long long * ptr,
+               unsigned int low, unsigned int high)
+ {
+       __asm__ __volatile__ (
+               "\n1:\t"
+               "movl (%0), %%eax\n\t"
+               "movl 4(%0), %%edx\n\t"
+               "lock cmpxchg8b (%0)\n\t"
+               "jnz 1b"
+               : /* no outputs */
+               :       "D"(ptr),
+                       "b"(low),
+                       "c"(high)
+               :       "ax","dx","memory");
+ }
+ static inline void __set_64bit_constant (unsigned long long *ptr,
+                                                unsigned long long value)
+ {
+       __set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
+ }
+ #define ll_low(x)     *(((unsigned int*)&(x))+0)
+ #define ll_high(x)    *(((unsigned int*)&(x))+1)
+ static inline void __set_64bit_var (unsigned long long *ptr,
+                        unsigned long long value)
+ {
+       __set_64bit(ptr,ll_low(value), ll_high(value));
+ }
+ #define set_64bit(ptr,value) \
+ (__builtin_constant_p(value) ? \
+  __set_64bit_constant(ptr, value) : \
+  __set_64bit_var(ptr, value) )
+ #define _set_64bit(ptr,value) \
+ (__builtin_constant_p(value) ? \
+  __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
+  __set_64bit(ptr, ll_low(value), ll_high(value)) )
+ /*
+  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+  * Note 2: xchg has side effect, so that attribute volatile is necessary,
+  *      but generally the primitive is invalid, *ptr is output argument. --ANK
+  */
+ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+ {
+       switch (size) {
+               case 1:
+                       __asm__ __volatile__("xchgb %b0,%1"
+                               :"=q" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 2:
+                       __asm__ __volatile__("xchgw %w0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+               case 4:
+                       __asm__ __volatile__("xchgl %0,%1"
+                               :"=r" (x)
+                               :"m" (*__xg(ptr)), "0" (x)
+                               :"memory");
+                       break;
+       }
+       return x;
+ }
+ /*
+  * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+  * store NEW in MEM.  Return the initial value in MEM.  Success is
+  * indicated by comparing RETURN with OLD.
+  */
+ #ifdef CONFIG_X86_CMPXCHG
+ #define __HAVE_ARCH_CMPXCHG 1
+ #endif
+ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                     unsigned long new, int size)
+ {
+       unsigned long prev;
+       switch (size) {
+       case 1:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 2:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 4:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       }
+       return old;
+ }
+ #define cmpxchg(ptr,o,n)\
+       ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+                                       (unsigned long)(n),sizeof(*(ptr))))
+     
+ #ifdef __KERNEL__
+ struct alt_instr { 
+       __u8 *instr;            /* original instruction */
+       __u8 *replacement;
+       __u8  cpuid;            /* cpuid bit set for replacement */
+       __u8  instrlen;         /* length of original instruction */
+       __u8  replacementlen;   /* length of new instruction, <= instrlen */ 
+       __u8  pad;
+ }; 
+ #endif
+ /* 
+  * Alternative instructions for different CPU types or capabilities.
+  * 
+  * This allows to use optimized instructions even on generic binary
+  * kernels.
+  * 
+  * length of oldinstr must be longer or equal the length of newinstr
+  * It can be padded with nops as needed.
+  * 
+  * For non barrier like inlines please define new variants
+  * without volatile and memory clobber.
+  */
+ #define alternative(oldinstr, newinstr, feature)      \
+       asm volatile ("661:\n\t" oldinstr "\n662:\n"                 \
+                     ".section .altinstructions,\"a\"\n"            \
+                     "  .align 4\n"                                   \
+                     "  .long 661b\n"            /* label */          \
+                     "  .long 663f\n"            /* new instruction */         \
+                     "  .byte %c0\n"             /* feature bit */    \
+                     "  .byte 662b-661b\n"       /* sourcelen */      \
+                     "  .byte 664f-663f\n"       /* replacementlen */ \
+                     ".previous\n"                                             \
+                     ".section .altinstr_replacement,\"ax\"\n"                 \
+                     "663:\n\t" newinstr "\n664:\n"   /* replacement */    \
+                     ".previous" :: "i" (feature) : "memory")  
+ /*
+  * Alternative inline assembly with input.
+  * 
+  * Pecularities:
+  * No memory clobber here. 
+  * Argument numbers start with 1.
+  * Best is to use constraints that are fixed size (like (%1) ... "r")
+  * If you use variable sized constraints like "m" or "g" in the 
+  * replacement maake sure to pad to the worst case length.
+  */
+ #define alternative_input(oldinstr, newinstr, feature, input...)              \
+       asm volatile ("661:\n\t" oldinstr "\n662:\n"                            \
+                     ".section .altinstructions,\"a\"\n"                       \
+                     "  .align 4\n"                                            \
+                     "  .long 661b\n"            /* label */                   \
+                     "  .long 663f\n"            /* new instruction */         \
+                     "  .byte %c0\n"             /* feature bit */             \
+                     "  .byte 662b-661b\n"       /* sourcelen */               \
+                     "  .byte 664f-663f\n"       /* replacementlen */          \
+                     ".previous\n"                                             \
+                     ".section .altinstr_replacement,\"ax\"\n"                 \
+                     "663:\n\t" newinstr "\n664:\n"   /* replacement */        \
+                     ".previous" :: "i" (feature), ##input)
+ /*
+  * Force strict CPU ordering.
+  * And yes, this is required on UP too when we're talking
+  * to devices.
+  *
+  * For now, "wmb()" doesn't actually do anything, as all
+  * Intel CPU's follow what Intel calls a *Processor Order*,
+  * in which all writes are seen in the program order even
+  * outside the CPU.
+  *
+  * I expect future Intel CPU's to have a weaker ordering,
+  * but I'd also expect them to finally get their act together
+  * and add some real memory barriers if so.
+  *
+  * Some non intel clones support out of order store. wmb() ceases to be a
+  * nop for these.
+  */
+  
+ /* 
+  * Actually only lfence would be needed for mb() because all stores done 
+  * by the kernel should be already ordered. But keep a full barrier for now. 
+  */
+ #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+ #define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+ /**
+  * read_barrier_depends - Flush all pending reads that subsequents reads
+  * depend on.
+  *
+  * No data-dependent reads from memory-like regions are ever reordered
+  * over this barrier.  All reads preceding this primitive are guaranteed
+  * to access memory (but not necessarily other CPUs' caches) before any
+  * reads following this primitive that depend on the data return by
+  * any of the preceding reads.  This primitive is much lighter weight than
+  * rmb() on most CPUs, and is never heavier weight than is
+  * rmb().
+  *
+  * These ordering constraints are respected by both the local CPU
+  * and the compiler.
+  *
+  * Ordering is not guaranteed by anything other than these primitives,
+  * not even by data dependencies.  See the documentation for
+  * memory_barrier() for examples and URLs to more information.
+  *
+  * For example, the following code would force ordering (the initial
+  * value of "a" is zero, "b" is one, and "p" is "&a"):
+  *
+  * <programlisting>
+  *    CPU 0                           CPU 1
+  *
+  *    b = 2;
+  *    memory_barrier();
+  *    p = &b;                         q = p;
+  *                                    read_barrier_depends();
+  *                                    d = *q;
+  * </programlisting>
+  *
+  * because the read of "*q" depends on the read of "p" and these
+  * two reads are separated by a read_barrier_depends().  However,
+  * the following code, with the same initial values for "a" and "b":
+  *
+  * <programlisting>
+  *    CPU 0                           CPU 1
+  *
+  *    a = 2;
+  *    memory_barrier();
+  *    b = 3;                          y = b;
+  *                                    read_barrier_depends();
+  *                                    x = a;
+  * </programlisting>
+  *
+  * does not enforce ordering, since there is no data dependency between
+  * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+  * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+  * in cases like thiswhere there are no data dependencies.
+  **/
+ #define read_barrier_depends()        do { } while(0)
+ #ifdef CONFIG_X86_OOSTORE
+ /* Actually there are no OOO store capable CPUs for now that do SSE, 
+    but make it already an possibility. */
+ #define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+ #else
+ #define wmb() __asm__ __volatile__ ("": : :"memory")
+ #endif
+ #ifdef CONFIG_SMP
+ #define smp_mb()      mb()
+ #define smp_rmb()     rmb()
+ #define smp_wmb()     wmb()
+ #define smp_read_barrier_depends()    read_barrier_depends()
+ #define set_mb(var, value) do { xchg(&var, value); } while (0)
+ #else
+ #define smp_mb()      barrier()
+ #define smp_rmb()     barrier()
+ #define smp_wmb()     barrier()
+ #define smp_read_barrier_depends()    do { } while(0)
+ #define set_mb(var, value) do { var = value; barrier(); } while (0)
+ #endif
+ #define set_wmb(var, value) do { var = value; wmb(); } while (0)
+ /* interrupt control.. */
+ /* 
+  * The use of 'barrier' in the following reflects their use as local-lock
+  * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
 -      HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask = 1;    \
++ * critical operations are executed. All critical operations must complete
+  * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
+  * includes these barriers, for example.
+  */
+ #define __cli()                                                               \
+ do {                                                                  \
 -      shared_info_t *_shared = HYPERVISOR_shared_info;                \
++      vcpu_info_t *_vcpu;                                             \
++      preempt_disable();                                              \
++      _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
++      _vcpu->evtchn_upcall_mask = 1;                                  \
++      preempt_enable_no_resched();                                    \
+       barrier();                                                      \
+ } while (0)
+ #define __sti()                                                               \
+ do {                                                                  \
 -      _shared->vcpu_data[0].evtchn_upcall_mask = 0;                   \
++      vcpu_info_t *_vcpu;                                             \
+       barrier();                                                      \
 -      if ( unlikely(_shared->vcpu_data[0].evtchn_upcall_pending) )    \
 -      force_evtchn_callback();                                        \
++      preempt_disable();                                              \
++      _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
++      _vcpu->evtchn_upcall_mask = 0;                                  \
+       barrier(); /* unmask then check (avoid races) */                \
 -      (x) = HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask;  \
++      if ( unlikely(_vcpu->evtchn_upcall_pending) )                   \
++              force_evtchn_callback();                                \
++      preempt_enable();                                               \
+ } while (0)
+ #define __save_flags(x)                                                       \
+ do {                                                                  \
 -      shared_info_t *_shared = HYPERVISOR_shared_info;                \
++      vcpu_info_t *_vcpu;                                             \
++      _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
++      (x) = _vcpu->evtchn_upcall_mask;                                \
+ } while (0)
+ #define __restore_flags(x)                                            \
+ do {                                                                  \
 -      if ( (_shared->vcpu_data[0].evtchn_upcall_mask = (x)) == 0 ) {  \
 -      barrier(); /* unmask then check (avoid races) */                \
 -      if ( unlikely(_shared->vcpu_data[0].evtchn_upcall_pending) )    \
 -          force_evtchn_callback();                                    \
 -      }                                                               \
++      vcpu_info_t *_vcpu;                                             \
+       barrier();                                                      \
 -#define safe_halt()        ((void)0)
++      preempt_disable();                                              \
++      _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
++      if ((_vcpu->evtchn_upcall_mask = (x)) == 0) {                   \
++              barrier(); /* unmask then check (avoid races) */        \
++              if ( unlikely(_vcpu->evtchn_upcall_pending) )           \
++                      force_evtchn_callback();                        \
++              preempt_enable();                                       \
++      } else                                                          \
++              preempt_enable_no_resched();                            \
+ } while (0)
 -      (x) = HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask;  \
 -      HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask = 1;    \
 -      barrier();                                                      \
 -} while (0)
 -
 -#define __save_and_sti(x)                                             \
 -do {                                                                  \
 -      shared_info_t *_shared = HYPERVISOR_shared_info;                \
++#define safe_halt()           ((void)0)
+ #define __save_and_cli(x)                                             \
+ do {                                                                  \
 -      (x) = _shared->vcpu_data[0].evtchn_upcall_mask;                 \
 -      _shared->vcpu_data[0].evtchn_upcall_mask = 0;                   \
 -      barrier(); /* unmask then check (avoid races) */                \
 -      if ( unlikely(_shared->vcpu_data[0].evtchn_upcall_pending) )    \
 -      force_evtchn_callback();                                        \
++      vcpu_info_t *_vcpu;                                             \
++      preempt_disable();                                              \
++      _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
++      (x) = _vcpu->evtchn_upcall_mask;                                \
++      _vcpu->evtchn_upcall_mask = 1;                                  \
++      preempt_enable_no_resched();                                    \
+       barrier();                                                      \
 -#define irqs_disabled() HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask
+ } while (0)
+ #define local_irq_save(x)     __save_and_cli(x)
+ #define local_irq_restore(x)  __restore_flags(x)
+ #define local_save_flags(x)   __save_flags(x)
+ #define local_irq_disable()   __cli()
+ #define local_irq_enable()    __sti()
++#define irqs_disabled()                       \
++    HYPERVISOR_shared_info->vcpu_data[smp_processor_id()].evtchn_upcall_mask
+ /*
+  * disable hlt during certain critical i/o operations
+  */
+ #define HAVE_DISABLE_HLT
+ void disable_hlt(void);
+ void enable_hlt(void);
+ extern int es7000_plat;
+ #endif
index 0000000000000000000000000000000000000000,d6f0b0b5459c69711c0df560a1990019b851c913..a85bf4ba61c316dcaa11dfa520d53de61a5222b5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,107 +1,110 @@@
 -/* Force a proper event-channel callback from Xen. */
 -void force_evtchn_callback(void);
 -
+ /******************************************************************************
+  * evtchn.h
+  * 
+  * Communication via Xen event channels.
+  * Also definitions for the device that demuxes notifications to userspace.
+  * 
+  * Copyright (c) 2004, K A Fraser
+  * 
+  * This file may be distributed separately from the Linux kernel, or
+  * incorporated into other software packages, subject to the following license:
+  * 
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+  * of this source file (the "Software"), to deal in the Software without
+  * restriction, including without limitation the rights to use, copy, modify,
+  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  * and to permit persons to whom the Software is furnished to do so, subject to
+  * the following conditions:
+  * 
+  * The above copyright notice and this permission notice shall be included in
+  * all copies or substantial portions of the Software.
+  * 
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  * IN THE SOFTWARE.
+  */
+ #ifndef __ASM_EVTCHN_H__
+ #define __ASM_EVTCHN_H__
+ #include <linux/config.h>
+ #include <asm-xen/hypervisor.h>
+ #include <asm/ptrace.h>
+ #include <asm/synch_bitops.h>
+ #include <asm-xen/xen-public/event_channel.h>
++#include <linux/smp.h>
+ /*
+  * LOW-LEVEL DEFINITIONS
+  */
 -         !synch_test_and_set_bit(port>>5, &s->evtchn_pending_sel) )
+ /* Entry point for notifications into Linux subsystems. */
+ asmlinkage void evtchn_do_upcall(struct pt_regs *regs);
+ /* Entry point for notifications into the userland character device. */
+ void evtchn_device_upcall(int port);
++#ifdef XEN_EVTCHN_MASK_OPS
++
+ static inline void mask_evtchn(int port)
+ {
+     shared_info_t *s = HYPERVISOR_shared_info;
+     synch_set_bit(port, &s->evtchn_mask[0]);
+ }
+ static inline void unmask_evtchn(int port)
+ {
+     shared_info_t *s = HYPERVISOR_shared_info;
++    vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()];
+     synch_clear_bit(port, &s->evtchn_mask[0]);
+     /*
+      * The following is basically the equivalent of 'hw_resend_irq'. Just like
+      * a real IO-APIC we 'lose the interrupt edge' if the channel is masked.
+      */
+     if (  synch_test_bit        (port,    &s->evtchn_pending[0]) && 
 -        s->vcpu_data[0].evtchn_upcall_pending = 1;
 -        if ( !s->vcpu_data[0].evtchn_upcall_mask )
++         !synch_test_and_set_bit(port>>5, &vcpu_info->evtchn_pending_sel) )
+     {
++        vcpu_info->evtchn_upcall_pending = 1;
++        if ( !vcpu_info->evtchn_upcall_mask )
+             force_evtchn_callback();
+     }
+ }
++#endif /* XEN_EVTCHN_MASK_OPS */
++
+ static inline void clear_evtchn(int port)
+ {
+     shared_info_t *s = HYPERVISOR_shared_info;
+     synch_clear_bit(port, &s->evtchn_pending[0]);
+ }
+ static inline void notify_via_evtchn(int port)
+ {
+     evtchn_op_t op;
+     op.cmd = EVTCHNOP_send;
+     op.u.send.local_port = port;
+     (void)HYPERVISOR_event_channel_op(&op);
+ }
+ /*
+  * CHARACTER-DEVICE DEFINITIONS
+  */
+ /* /dev/xen/evtchn resides at device number major=10, minor=201 */
+ #define EVTCHN_MINOR 201
+ /* /dev/xen/evtchn ioctls: */
+ /* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
+ #define EVTCHN_RESET  _IO('E', 1)
+ /* EVTCHN_BIND: Bind to teh specified event-channel port. */
+ #define EVTCHN_BIND   _IO('E', 2)
+ /* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
+ #define EVTCHN_UNBIND _IO('E', 3)
+ #endif /* __ASM_EVTCHN_H__ */
index 0000000000000000000000000000000000000000,ef755a4e7d16e31ec89d8dbf9c0d653429544895..024452bdbd6f43243ec64b4fe7fc6ebeee79a0fe
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,556 +1,573 @@@
 -extern unsigned int mmu_update_queue_idx;
 -
+ /******************************************************************************
+  * hypervisor.h
+  * 
+  * Linux-specific hypervisor handling.
+  * 
+  * Copyright (c) 2002-2004, K A Fraser
+  * 
+  * This file may be distributed separately from the Linux kernel, or
+  * incorporated into other software packages, subject to the following license:
+  * 
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+  * of this source file (the "Software"), to deal in the Software without
+  * restriction, including without limitation the rights to use, copy, modify,
+  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  * and to permit persons to whom the Software is furnished to do so, subject to
+  * the following conditions:
+  * 
+  * The above copyright notice and this permission notice shall be included in
+  * all copies or substantial portions of the Software.
+  * 
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  * IN THE SOFTWARE.
+  */
+ #ifndef __HYPERVISOR_H__
+ #define __HYPERVISOR_H__
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/version.h>
+ #include <asm-xen/xen-public/xen.h>
+ #include <asm-xen/xen-public/dom0_ops.h>
+ #include <asm-xen/xen-public/io/domain_controller.h>
+ #include <asm/ptrace.h>
+ #include <asm/page.h>
+ /* arch/xen/i386/kernel/setup.c */
+ union xen_start_info_union
+ {
+     start_info_t xen_start_info;
+     char padding[512];
+ };
+ extern union xen_start_info_union xen_start_info_union;
+ #define xen_start_info (xen_start_info_union.xen_start_info)
++/* arch/xen/kernel/evtchn.c */
++/* Force a proper event-channel callback from Xen. */
++void force_evtchn_callback(void);
++
+ /* arch/xen/kernel/process.c */
+ void xen_cpu_idle (void);
+ /* arch/xen/i386/kernel/hypervisor.c */
+ void do_hypervisor_callback(struct pt_regs *regs);
+ /* arch/xen/i386/kernel/head.S */
+ void lgdt_finish(void);
+ /* arch/xen/i386/mm/hypervisor.c */
+ /*
+  * NB. ptr values should be PHYSICAL, not MACHINE. 'vals' should be already
+  * be MACHINE addresses.
+  */
 -static inline int flush_page_update_queue(void)
 -{
 -    unsigned int idx = mmu_update_queue_idx;
 -    if ( idx != 0 ) _flush_page_update_queue();
 -    return idx;
 -}
+ void queue_l1_entry_update(pte_t *ptr, unsigned long val);
+ void queue_l2_entry_update(pmd_t *ptr, unsigned long val);
+ void queue_pt_switch(unsigned long ptr);
+ void queue_tlb_flush(void);
+ void queue_invlpg(unsigned long ptr);
+ void queue_pgd_pin(unsigned long ptr);
+ void queue_pgd_unpin(unsigned long ptr);
+ void queue_pte_pin(unsigned long ptr);
+ void queue_pte_unpin(unsigned long ptr);
+ void queue_set_ldt(unsigned long ptr, unsigned long bytes);
+ void queue_machphys_update(unsigned long mfn, unsigned long pfn);
+ void xen_l1_entry_update(pte_t *ptr, unsigned long val);
+ void xen_l2_entry_update(pmd_t *ptr, unsigned long val);
+ void xen_pt_switch(unsigned long ptr);
+ void xen_tlb_flush(void);
+ void xen_invlpg(unsigned long ptr);
+ void xen_pgd_pin(unsigned long ptr);
+ void xen_pgd_unpin(unsigned long ptr);
+ void xen_pte_pin(unsigned long ptr);
+ void xen_pte_unpin(unsigned long ptr);
+ void xen_set_ldt(unsigned long ptr, unsigned long bytes);
+ void xen_machphys_update(unsigned long mfn, unsigned long pfn);
+ void _flush_page_update_queue(void);
++#define flush_page_update_queue() do {                                \
++    DECLARE_PER_CPU(unsigned int, mmu_update_queue_idx);      \
++    if (per_cpu(mmu_update_queue_idx, smp_processor_id()))    \
++      _flush_page_update_queue();                             \
++} while (0)
+ #define xen_flush_page_update_queue() (_flush_page_update_queue())
+ #define XEN_flush_page_update_queue() (_flush_page_update_queue())
+ void MULTICALL_flush_page_update_queue(void);
+ #ifdef CONFIG_XEN_PHYSDEV_ACCESS
+ /* Allocate a contiguous empty region of low memory. Return virtual start. */
+ unsigned long allocate_empty_lowmem_region(unsigned long pages);
+ #endif
+ /*
+  * Assembler stubs for hyper-calls.
+  */
+ static inline int
+ HYPERVISOR_set_trap_table(
+     trap_info_t *table)
+ {
+     int ret;
+     unsigned long ignore;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ignore)
+       : "0" (__HYPERVISOR_set_trap_table), "1" (table)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_mmu_update(
+     mmu_update_t *req, int count, int *success_count)
+ {
+     int ret;
+     unsigned long ign1, ign2, ign3;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+       : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
+         "3" (success_count)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_set_gdt(
+     unsigned long *frame_list, int entries)
+ {
+     int ret;
+     unsigned long ign1, ign2;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_stack_switch(
+     unsigned long ss, unsigned long esp)
+ {
+     int ret;
+     unsigned long ign1, ign2;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_set_callbacks(
+     unsigned long event_selector, unsigned long event_address,
+     unsigned long failsafe_selector, unsigned long failsafe_address)
+ {
+     int ret;
+     unsigned long ign1, ign2, ign3, ign4;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+       : "0" (__HYPERVISOR_set_callbacks), "1" (event_selector),
+         "2" (event_address), "3" (failsafe_selector), "4" (failsafe_address)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_fpu_taskswitch(
+     void)
+ {
+     int ret;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_yield(
+     void)
+ {
+     int ret;
+     unsigned long ign;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign)
+       : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_block(
+     void)
+ {
+     int ret;
+     unsigned long ign1;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_shutdown(
+     void)
+ {
+     int ret;
+     unsigned long ign1;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_sched_op),
+         "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
+         : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_reboot(
+     void)
+ {
+     int ret;
+     unsigned long ign1;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_sched_op),
+         "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
+         : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_suspend(
+     unsigned long srec)
+ {
+     int ret;
+     unsigned long ign1, ign2;
+     /* NB. On suspend, control software expects a suspend record in %esi. */
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=S" (ign2)
+       : "0" (__HYPERVISOR_sched_op),
+         "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)), 
+         "S" (srec) : "memory");
+     return ret;
+ }
+ static inline long
+ HYPERVISOR_set_timer_op(
+     u64 timeout)
+ {
+     int ret;
+     unsigned long timeout_hi = (unsigned long)(timeout>>32);
+     unsigned long timeout_lo = (unsigned long)timeout;
+     unsigned long ign1, ign2;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_set_timer_op), "b" (timeout_hi), "c" (timeout_lo)
+       : "memory");
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_dom0_op(
+     dom0_op_t *dom0_op)
+ {
+     int ret;
+     unsigned long ign1;
+     dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1)
+       : "0" (__HYPERVISOR_dom0_op), "1" (dom0_op)
+       : "memory");
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_set_debugreg(
+     int reg, unsigned long value)
+ {
+     int ret;
+     unsigned long ign1, ign2;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value)
+       : "memory" );
+     return ret;
+ }
+ static inline unsigned long
+ HYPERVISOR_get_debugreg(
+     int reg)
+ {
+     unsigned long ret;
+     unsigned long ign;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign)
+       : "0" (__HYPERVISOR_get_debugreg), "1" (reg)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_update_descriptor(
+     unsigned long ma, unsigned long word1, unsigned long word2)
+ {
+     int ret;
+     unsigned long ign1, ign2, ign3;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+       : "0" (__HYPERVISOR_update_descriptor), "1" (ma), "2" (word1),
+         "3" (word2)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_set_fast_trap(
+     int idx)
+ {
+     int ret;
+     unsigned long ign;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign)
+       : "0" (__HYPERVISOR_set_fast_trap), "1" (idx)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_dom_mem_op(
+     unsigned int op, unsigned long *extent_list,
+     unsigned long nr_extents, unsigned int extent_order)
+ {
+     int ret;
+     unsigned long ign1, ign2, ign3, ign4, ign5;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
+         "=D" (ign5)
+       : "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
+         "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
+         : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_multicall(
+     void *call_list, int nr_calls)
+ {
+     int ret;
+     unsigned long ign1, ign2;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_update_va_mapping(
+     unsigned long page_nr, pte_t new_val, unsigned long flags)
+ {
+     int ret;
+     unsigned long ign1, ign2, ign3;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+       : "0" (__HYPERVISOR_update_va_mapping), 
+           "1" (page_nr), "2" ((new_val).pte_low), "3" (flags)
+       : "memory" );
+     if ( unlikely(ret < 0) )
+     {
+         printk(KERN_ALERT "Failed update VA mapping: %08lx, %08lx, %08lx\n",
+                page_nr, (new_val).pte_low, flags);
+         BUG();
+     }
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_event_channel_op(
+     void *op)
+ {
+     int ret;
+     unsigned long ignore;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ignore)
+       : "0" (__HYPERVISOR_event_channel_op), "1" (op)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_xen_version(
+     int cmd)
+ {
+     int ret;
+     unsigned long ignore;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ignore)
+       : "0" (__HYPERVISOR_xen_version), "1" (cmd)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_console_io(
+     int cmd, int count, char *str)
+ {
+     int ret;
+     unsigned long ign1, ign2, ign3;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+       : "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_physdev_op(
+     void *physdev_op)
+ {
+     int ret;
+     unsigned long ign;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign)
+       : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_grant_table_op(
+     unsigned int cmd, void *uop, unsigned int count)
+ {
+     int ret;
+     unsigned long ign1, ign2, ign3;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+       : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (count), "3" (uop)
+       : "memory" );
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_update_va_mapping_otherdomain(
+     unsigned long page_nr, pte_t new_val, unsigned long flags, domid_t domid)
+ {
+     int ret;
+     unsigned long ign1, ign2, ign3, ign4;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+       : "0" (__HYPERVISOR_update_va_mapping_otherdomain),
+           "1" (page_nr), "2" ((new_val).pte_low), "3" (flags), "4" (domid) :
+         "memory" );
+     
+     return ret;
+ }
+ static inline int
+ HYPERVISOR_vm_assist(
+     unsigned int cmd, unsigned int type)
+ {
+     int ret;
+     unsigned long ign1, ign2;
+     __asm__ __volatile__ (
+         TRAP_INSTR
+         : "=a" (ret), "=b" (ign1), "=c" (ign2)
+       : "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type)
+       : "memory" );
+     return ret;
+ }
++static inline int
++HYPERVISOR_boot_vcpu(
++    unsigned long vcpu, full_execution_context_t *ctxt)
++{
++    int ret;
++    unsigned long ign1, ign2;
++
++    __asm__ __volatile__ (
++        TRAP_INSTR
++        : "=a" (ret), "=b" (ign1), "=c" (ign2)
++      : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt)
++      : "memory");
++
++    return ret;
++}
++
+ #endif /* __HYPERVISOR_H__ */
index 0000000000000000000000000000000000000000,ca169b57b90b6a07be8ad31f0816e456a5a04bbb..1f03675df0631164e6fe2baee641d18d03746d1d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,107 +1,115 @@@
 -extern multicall_entry_t multicall_list[];
 -extern int nr_multicall_ents;
+ /******************************************************************************
+  * multicall.h
+  * 
+  * Copyright (c) 2003-2004, K A Fraser
+  * 
+  * This file may be distributed separately from the Linux kernel, or
+  * incorporated into other software packages, subject to the following license:
+  * 
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+  * of this source file (the "Software"), to deal in the Software without
+  * restriction, including without limitation the rights to use, copy, modify,
+  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  * and to permit persons to whom the Software is furnished to do so, subject to
+  * the following conditions:
+  * 
+  * The above copyright notice and this permission notice shall be included in
+  * all copies or substantial portions of the Software.
+  * 
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  * IN THE SOFTWARE.
+  */
+ #ifndef __MULTICALL_H__
+ #define __MULTICALL_H__
+ #include <asm-xen/hypervisor.h>
 -    int i = nr_multicall_ents;
 -    multicall_list[i].op      = op;
 -    nr_multicall_ents = i+1;
++DECLARE_PER_CPU(multicall_entry_t, multicall_list[]);
++DECLARE_PER_CPU(int, nr_multicall_ents);
+ static inline void queue_multicall0(unsigned long op)
+ {
 -    int i = nr_multicall_ents;
 -    multicall_list[i].op      = op;
 -    multicall_list[i].args[0] = arg1;
 -    nr_multicall_ents = i+1;
++    int cpu = smp_processor_id();
++    int i = per_cpu(nr_multicall_ents, cpu);
++    per_cpu(multicall_list[i], cpu).op      = op;
++    per_cpu(nr_multicall_ents, cpu) = i+1;
+ }
+ static inline void queue_multicall1(unsigned long op, unsigned long arg1)
+ {
 -    int i = nr_multicall_ents;
 -    multicall_list[i].op      = op;
 -    multicall_list[i].args[0] = arg1;
 -    multicall_list[i].args[1] = arg2;
 -    nr_multicall_ents = i+1;
++    int cpu = smp_processor_id();
++    int i = per_cpu(nr_multicall_ents, cpu);
++    per_cpu(multicall_list[i], cpu).op      = op;
++    per_cpu(multicall_list[i], cpu).args[0] = arg1;
++    per_cpu(nr_multicall_ents, cpu) = i+1;
+ }
+ static inline void queue_multicall2(
+     unsigned long op, unsigned long arg1, unsigned long arg2)
+ {
 -    int i = nr_multicall_ents;
 -    multicall_list[i].op      = op;
 -    multicall_list[i].args[0] = arg1;
 -    multicall_list[i].args[1] = arg2;
 -    multicall_list[i].args[2] = arg3;
 -    nr_multicall_ents = i+1;
++    int cpu = smp_processor_id();
++    int i = per_cpu(nr_multicall_ents, cpu);
++    per_cpu(multicall_list[i], cpu).op      = op;
++    per_cpu(multicall_list[i], cpu).args[0] = arg1;
++    per_cpu(multicall_list[i], cpu).args[1] = arg2;
++    per_cpu(nr_multicall_ents, cpu) = i+1;
+ }
+ static inline void queue_multicall3(
+     unsigned long op, unsigned long arg1, unsigned long arg2,
+     unsigned long arg3)
+ {
 -    int i = nr_multicall_ents;
 -    multicall_list[i].op      = op;
 -    multicall_list[i].args[0] = arg1;
 -    multicall_list[i].args[1] = arg2;
 -    multicall_list[i].args[2] = arg3;
 -    multicall_list[i].args[3] = arg4;
 -    nr_multicall_ents = i+1;
++    int cpu = smp_processor_id();
++    int i = per_cpu(nr_multicall_ents, cpu);
++    per_cpu(multicall_list[i], cpu).op      = op;
++    per_cpu(multicall_list[i], cpu).args[0] = arg1;
++    per_cpu(multicall_list[i], cpu).args[1] = arg2;
++    per_cpu(multicall_list[i], cpu).args[2] = arg3;
++    per_cpu(nr_multicall_ents, cpu) = i+1;
+ }
+ static inline void queue_multicall4(
+     unsigned long op, unsigned long arg1, unsigned long arg2,
+     unsigned long arg3, unsigned long arg4)
+ {
 -    int i = nr_multicall_ents;
 -    multicall_list[i].op      = op;
 -    multicall_list[i].args[0] = arg1;
 -    multicall_list[i].args[1] = arg2;
 -    multicall_list[i].args[2] = arg3;
 -    multicall_list[i].args[3] = arg4;
 -    multicall_list[i].args[4] = arg5;
 -    nr_multicall_ents = i+1;
++    int cpu = smp_processor_id();
++    int i = per_cpu(nr_multicall_ents, cpu);
++    per_cpu(multicall_list[i], cpu).op      = op;
++    per_cpu(multicall_list[i], cpu).args[0] = arg1;
++    per_cpu(multicall_list[i], cpu).args[1] = arg2;
++    per_cpu(multicall_list[i], cpu).args[2] = arg3;
++    per_cpu(multicall_list[i], cpu).args[3] = arg4;
++    per_cpu(nr_multicall_ents, cpu) = i+1;
+ }
+ static inline void queue_multicall5(
+     unsigned long op, unsigned long arg1, unsigned long arg2,
+     unsigned long arg3, unsigned long arg4, unsigned long arg5)
+ {
 -    if ( unlikely(nr_multicall_ents == 0) ) return;
 -    (void)HYPERVISOR_multicall(multicall_list, nr_multicall_ents);
 -    nr_multicall_ents = 0;
++    int cpu = smp_processor_id();
++    int i = per_cpu(nr_multicall_ents, cpu);
++    per_cpu(multicall_list[i], cpu).op      = op;
++    per_cpu(multicall_list[i], cpu).args[0] = arg1;
++    per_cpu(multicall_list[i], cpu).args[1] = arg2;
++    per_cpu(multicall_list[i], cpu).args[2] = arg3;
++    per_cpu(multicall_list[i], cpu).args[3] = arg4;
++    per_cpu(multicall_list[i], cpu).args[4] = arg5;
++    per_cpu(nr_multicall_ents, cpu) = i+1;
+ }
+ static inline void execute_multicall_list(void)
+ {
++    int cpu = smp_processor_id();
++    if ( unlikely(per_cpu(nr_multicall_ents, cpu) == 0) ) return;
++    (void)HYPERVISOR_multicall(&per_cpu(multicall_list[0], cpu),
++                             per_cpu(nr_multicall_ents, cpu));
++    per_cpu(nr_multicall_ents, cpu) = 0;
+ }
+ #endif /* __MULTICALL_H__ */